blob: b3b95d917a82339652ec0674c8dfcd15faf81a96 [file] [log] [blame]
Romain Guy3d1728c2012-10-31 20:31:58 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.widget;
18
19import android.content.BroadcastReceiver;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.res.TypedArray;
25import android.database.ContentObserver;
26import android.net.Uri;
27import android.os.Handler;
28import android.os.SystemClock;
29import android.provider.Settings;
30import android.text.format.DateFormat;
31import android.util.AttributeSet;
Romain Guya9cfe672012-11-05 14:16:32 -080032import android.view.RemotableViewMethod;
Romain Guy3d1728c2012-10-31 20:31:58 -070033
34import com.android.internal.R;
35
36import java.util.Calendar;
37import java.util.TimeZone;
38
Elliott Hughescdafd372013-03-18 17:21:33 -070039import libcore.icu.LocaleData;
40
Romain Guy3d1728c2012-10-31 20:31:58 -070041import static android.view.ViewDebug.ExportedProperty;
42import static android.widget.RemoteViews.*;
43
44/**
45 * <p><code>TextClock</code> can display the current date and/or time as
46 * a formatted string.</p>
Elliott Hughescdafd372013-03-18 17:21:33 -070047 *
Romain Guy3d1728c2012-10-31 20:31:58 -070048 * <p>This view honors the 24-hour format system setting. As such, it is
49 * possible and recommended to provide two different formatting patterns:
50 * one to display the date/time in 24-hour mode and one to display the
Elliott Hughescdafd372013-03-18 17:21:33 -070051 * date/time in 12-hour mode. Most callers will want to use the defaults,
52 * though, which will be appropriate for the user's locale.</p>
53 *
Romain Guy3d1728c2012-10-31 20:31:58 -070054 * <p>It is possible to determine whether the system is currently in
55 * 24-hour mode by calling {@link #is24HourModeEnabled()}.</p>
Elliott Hughescdafd372013-03-18 17:21:33 -070056 *
Romain Guy3d1728c2012-10-31 20:31:58 -070057 * <p>The rules used by this widget to decide how to format the date and
58 * time are the following:</p>
59 * <ul>
60 * <li>In 24-hour mode:
61 * <ul>
62 * <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li>
63 * <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li>
Elliott Hughescdafd372013-03-18 17:21:33 -070064 * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code h:mm a}</li>
Romain Guy3d1728c2012-10-31 20:31:58 -070065 * </ul>
66 * </li>
67 * <li>In 12-hour mode:
68 * <ul>
69 * <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li>
70 * <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li>
Elliott Hughescdafd372013-03-18 17:21:33 -070071 * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code HH:mm}</li>
Romain Guy3d1728c2012-10-31 20:31:58 -070072 * </ul>
73 * </li>
74 * </ul>
Elliott Hughescdafd372013-03-18 17:21:33 -070075 *
Romain Guy3d1728c2012-10-31 20:31:58 -070076 * <p>The {@link CharSequence} instances used as formatting patterns when calling either
77 * {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can
Elliott Hughescdafd372013-03-18 17:21:33 -070078 * contain styling information. To do so, use a {@link android.text.Spanned} object.
79 * Note that if you customize these strings, it is your responsibility to supply strings
80 * appropriate for formatting dates and/or times in the user's locale.</p>
81 *
Romain Guy3d1728c2012-10-31 20:31:58 -070082 * @attr ref android.R.styleable#TextClock_format12Hour
83 * @attr ref android.R.styleable#TextClock_format24Hour
84 * @attr ref android.R.styleable#TextClock_timeZone
85 */
86@RemoteView
87public class TextClock extends TextView {
88 /**
Elliott Hughescdafd372013-03-18 17:21:33 -070089 * The default formatting pattern in 12-hour mode. This pattern is used
Romain Guy3d1728c2012-10-31 20:31:58 -070090 * if {@link #setFormat12Hour(CharSequence)} is called with a null pattern
91 * or if no pattern was specified when creating an instance of this class.
Elliott Hughescdafd372013-03-18 17:21:33 -070092 *
Romain Guy3d1728c2012-10-31 20:31:58 -070093 * This default pattern shows only the time, hours and minutes, and an am/pm
94 * indicator.
95 *
96 * @see #setFormat12Hour(CharSequence)
97 * @see #getFormat12Hour()
Romain Guy09b19942013-04-30 11:19:39 -070098 *
Elliott Hughescdafd372013-03-18 17:21:33 -070099 * @deprecated Let the system use locale-appropriate defaults instead.
Romain Guy3d1728c2012-10-31 20:31:58 -0700100 */
Elliott Hughescdafd372013-03-18 17:21:33 -0700101 public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm a";
Romain Guy3d1728c2012-10-31 20:31:58 -0700102
103 /**
Elliott Hughescdafd372013-03-18 17:21:33 -0700104 * The default formatting pattern in 24-hour mode. This pattern is used
Romain Guy3d1728c2012-10-31 20:31:58 -0700105 * if {@link #setFormat24Hour(CharSequence)} is called with a null pattern
106 * or if no pattern was specified when creating an instance of this class.
107 *
108 * This default pattern shows only the time, hours and minutes.
Elliott Hughescdafd372013-03-18 17:21:33 -0700109 *
110 * @see #setFormat24Hour(CharSequence)
111 * @see #getFormat24Hour()
Romain Guy09b19942013-04-30 11:19:39 -0700112 *
Elliott Hughescdafd372013-03-18 17:21:33 -0700113 * @deprecated Let the system use locale-appropriate defaults instead.
Romain Guy3d1728c2012-10-31 20:31:58 -0700114 */
Elliott Hughescdafd372013-03-18 17:21:33 -0700115 public static final CharSequence DEFAULT_FORMAT_24_HOUR = "H:mm";
Romain Guy3d1728c2012-10-31 20:31:58 -0700116
Elliott Hughescdafd372013-03-18 17:21:33 -0700117 private CharSequence mFormat12;
118 private CharSequence mFormat24;
Romain Guy3d1728c2012-10-31 20:31:58 -0700119
120 @ExportedProperty
121 private CharSequence mFormat;
122 @ExportedProperty
123 private boolean mHasSeconds;
124
125 private boolean mAttached;
126
127 private Calendar mTime;
128 private String mTimeZone;
129
130 private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
131 @Override
132 public void onChange(boolean selfChange) {
133 chooseFormat();
134 onTimeChanged();
135 }
136
137 @Override
138 public void onChange(boolean selfChange, Uri uri) {
139 chooseFormat();
140 onTimeChanged();
141 }
142 };
143
144 private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
145 @Override
146 public void onReceive(Context context, Intent intent) {
Romain Guya76f7db2012-11-06 17:35:23 -0800147 if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
148 final String timeZone = intent.getStringExtra("time-zone");
149 createTime(timeZone);
Romain Guy3d1728c2012-10-31 20:31:58 -0700150 }
Romain Guya76f7db2012-11-06 17:35:23 -0800151 onTimeChanged();
Romain Guy3d1728c2012-10-31 20:31:58 -0700152 }
153 };
154
155 private final Runnable mTicker = new Runnable() {
156 public void run() {
157 onTimeChanged();
158
159 long now = SystemClock.uptimeMillis();
160 long next = now + (1000 - now % 1000);
161
162 getHandler().postAtTime(mTicker, next);
163 }
164 };
165
166 /**
Romain Guy09b19942013-04-30 11:19:39 -0700167 * Creates a new clock using the default patterns for the current locale.
Elliott Hughescdafd372013-03-18 17:21:33 -0700168 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700169 * @param context The Context the view is running in, through which it can
170 * access the current theme, resources, etc.
171 */
172 @SuppressWarnings("UnusedDeclaration")
173 public TextClock(Context context) {
174 super(context);
175 init();
176 }
177
178 /**
179 * Creates a new clock inflated from XML. This object's properties are
180 * intialized from the attributes specified in XML.
Elliott Hughescdafd372013-03-18 17:21:33 -0700181 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700182 * This constructor uses a default style of 0, so the only attribute values
183 * applied are those in the Context's Theme and the given AttributeSet.
184 *
185 * @param context The Context the view is running in, through which it can
186 * access the current theme, resources, etc.
187 * @param attrs The attributes of the XML tag that is inflating the view
188 */
189 @SuppressWarnings("UnusedDeclaration")
190 public TextClock(Context context, AttributeSet attrs) {
191 this(context, attrs, 0);
192 }
193
194 /**
195 * Creates a new clock inflated from XML. This object's properties are
196 * intialized from the attributes specified in XML.
197 *
198 * @param context The Context the view is running in, through which it can
199 * access the current theme, resources, etc.
200 * @param attrs The attributes of the XML tag that is inflating the view
201 * @param defStyle The default style to apply to this view. If 0, no style
202 * will be applied (beyond what is included in the theme). This may
203 * either be an attribute resource, whose value will be retrieved
204 * from the current theme, or an explicit style resource
205 */
206 public TextClock(Context context, AttributeSet attrs, int defStyle) {
207 super(context, attrs, defStyle);
208
209 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextClock, defStyle, 0);
210 try {
Elliott Hughescdafd372013-03-18 17:21:33 -0700211 mFormat12 = a.getText(R.styleable.TextClock_format12Hour);
212 mFormat24 = a.getText(R.styleable.TextClock_format24Hour);
Romain Guy3d1728c2012-10-31 20:31:58 -0700213 mTimeZone = a.getString(R.styleable.TextClock_timeZone);
214 } finally {
215 a.recycle();
216 }
217
218 init();
219 }
220
221 private void init() {
Elliott Hughescdafd372013-03-18 17:21:33 -0700222 if (mFormat12 == null || mFormat24 == null) {
223 LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
224 if (mFormat12 == null) {
225 mFormat12 = ld.timeFormat12;
226 }
227 if (mFormat24 == null) {
228 mFormat24 = ld.timeFormat24;
229 }
230 }
231
Romain Guy3d1728c2012-10-31 20:31:58 -0700232 createTime(mTimeZone);
233 // Wait until onAttachedToWindow() to handle the ticker
234 chooseFormat(false);
235 }
236
237 private void createTime(String timeZone) {
238 if (timeZone != null) {
239 mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
240 } else {
241 mTime = Calendar.getInstance();
242 }
243 }
244
245 /**
246 * Returns the formatting pattern used to display the date and/or time
247 * in 12-hour mode. The formatting pattern syntax is described in
248 * {@link DateFormat}.
Elliott Hughescdafd372013-03-18 17:21:33 -0700249 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700250 * @return A {@link CharSequence} or null.
Elliott Hughescdafd372013-03-18 17:21:33 -0700251 *
252 * @see #setFormat12Hour(CharSequence)
253 * @see #is24HourModeEnabled()
Romain Guy3d1728c2012-10-31 20:31:58 -0700254 */
255 @ExportedProperty
256 public CharSequence getFormat12Hour() {
257 return mFormat12;
258 }
259
260 /**
Romain Guy09b19942013-04-30 11:19:39 -0700261 * <p>Specifies the formatting pattern used to display the date and/or time
Romain Guy3d1728c2012-10-31 20:31:58 -0700262 * in 12-hour mode. The formatting pattern syntax is described in
Romain Guy09b19942013-04-30 11:19:39 -0700263 * {@link DateFormat}.</p>
Romain Guy3d1728c2012-10-31 20:31:58 -0700264 *
Romain Guy09b19942013-04-30 11:19:39 -0700265 * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
Romain Guy3d1728c2012-10-31 20:31:58 -0700266 * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
Romain Guy09b19942013-04-30 11:19:39 -0700267 * are set to null, the default pattern for the current locale will be used
268 * instead.</p>
269 *
270 * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
271 * you supply a format string generated by
272 * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
273 * takes care of generating a format string adapted to the desired locale.</p>
274 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700275 *
276 * @param format A date/time formatting pattern as described in {@link DateFormat}
Elliott Hughescdafd372013-03-18 17:21:33 -0700277 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700278 * @see #getFormat12Hour()
279 * @see #is24HourModeEnabled()
Romain Guy09b19942013-04-30 11:19:39 -0700280 * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
Romain Guy3d1728c2012-10-31 20:31:58 -0700281 * @see DateFormat
Elliott Hughescdafd372013-03-18 17:21:33 -0700282 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700283 * @attr ref android.R.styleable#TextClock_format12Hour
284 */
Romain Guya9cfe672012-11-05 14:16:32 -0800285 @RemotableViewMethod
Romain Guy3d1728c2012-10-31 20:31:58 -0700286 public void setFormat12Hour(CharSequence format) {
287 mFormat12 = format;
288
289 chooseFormat();
290 onTimeChanged();
291 }
292
293 /**
294 * Returns the formatting pattern used to display the date and/or time
295 * in 24-hour mode. The formatting pattern syntax is described in
296 * {@link DateFormat}.
297 *
298 * @return A {@link CharSequence} or null.
299 *
300 * @see #setFormat24Hour(CharSequence)
301 * @see #is24HourModeEnabled()
302 */
303 @ExportedProperty
304 public CharSequence getFormat24Hour() {
305 return mFormat24;
306 }
307
308 /**
Romain Guy09b19942013-04-30 11:19:39 -0700309 * <p>Specifies the formatting pattern used to display the date and/or time
Romain Guy3d1728c2012-10-31 20:31:58 -0700310 * in 24-hour mode. The formatting pattern syntax is described in
Romain Guy09b19942013-04-30 11:19:39 -0700311 * {@link DateFormat}.</p>
Elliott Hughescdafd372013-03-18 17:21:33 -0700312 *
Romain Guy09b19942013-04-30 11:19:39 -0700313 * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
314 * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
315 * are set to null, the default pattern for the current locale will be used
316 * instead.</p>
317 *
318 * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
319 * you supply a format string generated by
320 * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
321 * takes care of generating a format string adapted to the desired locale.</p>
Romain Guy3d1728c2012-10-31 20:31:58 -0700322 *
323 * @param format A date/time formatting pattern as described in {@link DateFormat}
324 *
325 * @see #getFormat24Hour()
Elliott Hughescdafd372013-03-18 17:21:33 -0700326 * @see #is24HourModeEnabled()
Romain Guy09b19942013-04-30 11:19:39 -0700327 * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
Romain Guy3d1728c2012-10-31 20:31:58 -0700328 * @see DateFormat
329 *
330 * @attr ref android.R.styleable#TextClock_format24Hour
331 */
Romain Guya9cfe672012-11-05 14:16:32 -0800332 @RemotableViewMethod
Romain Guy3d1728c2012-10-31 20:31:58 -0700333 public void setFormat24Hour(CharSequence format) {
334 mFormat24 = format;
335
336 chooseFormat();
337 onTimeChanged();
338 }
339
340 /**
341 * Indicates whether the system is currently using the 24-hour mode.
Elliott Hughescdafd372013-03-18 17:21:33 -0700342 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700343 * When the system is in 24-hour mode, this view will use the pattern
344 * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
345 * returned by {@link #getFormat12Hour()} is used instead.
Elliott Hughescdafd372013-03-18 17:21:33 -0700346 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700347 * If either one of the formats is null, the other format is used. If
Romain Guy09b19942013-04-30 11:19:39 -0700348 * both formats are null, the default formats for the current locale are used.
Elliott Hughescdafd372013-03-18 17:21:33 -0700349 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700350 * @return true if time should be displayed in 24-hour format, false if it
351 * should be displayed in 12-hour format.
Elliott Hughescdafd372013-03-18 17:21:33 -0700352 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700353 * @see #setFormat12Hour(CharSequence)
Elliott Hughescdafd372013-03-18 17:21:33 -0700354 * @see #getFormat12Hour()
Romain Guy3d1728c2012-10-31 20:31:58 -0700355 * @see #setFormat24Hour(CharSequence)
Elliott Hughescdafd372013-03-18 17:21:33 -0700356 * @see #getFormat24Hour()
Romain Guy3d1728c2012-10-31 20:31:58 -0700357 */
358 public boolean is24HourModeEnabled() {
359 return DateFormat.is24HourFormat(getContext());
360 }
361
362 /**
363 * Indicates which time zone is currently used by this view.
Elliott Hughescdafd372013-03-18 17:21:33 -0700364 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700365 * @return The ID of the current time zone or null if the default time zone,
366 * as set by the user, must be used
367 *
368 * @see TimeZone
369 * @see java.util.TimeZone#getAvailableIDs()
Elliott Hughescdafd372013-03-18 17:21:33 -0700370 * @see #setTimeZone(String)
Romain Guy3d1728c2012-10-31 20:31:58 -0700371 */
372 public String getTimeZone() {
373 return mTimeZone;
374 }
375
376 /**
377 * Sets the specified time zone to use in this clock. When the time zone
378 * is set through this method, system time zone changes (when the user
379 * sets the time zone in settings for instance) will be ignored.
380 *
381 * @param timeZone The desired time zone's ID as specified in {@link TimeZone}
382 * or null to user the time zone specified by the user
383 * (system time zone)
384 *
385 * @see #getTimeZone()
386 * @see java.util.TimeZone#getAvailableIDs()
387 * @see TimeZone#getTimeZone(String)
388 *
389 * @attr ref android.R.styleable#TextClock_timeZone
390 */
Romain Guya9cfe672012-11-05 14:16:32 -0800391 @RemotableViewMethod
Romain Guy3d1728c2012-10-31 20:31:58 -0700392 public void setTimeZone(String timeZone) {
393 mTimeZone = timeZone;
394
395 createTime(timeZone);
396 onTimeChanged();
397 }
398
399 /**
400 * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
401 * depending on whether the user has selected 24-hour format.
Elliott Hughescdafd372013-03-18 17:21:33 -0700402 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700403 * Calling this method does not schedule or unschedule the time ticker.
404 */
405 private void chooseFormat() {
406 chooseFormat(true);
407 }
408
409 /**
Jeff Sharkey06c5f8a2012-12-04 09:53:44 -0800410 * Returns the current format string. Always valid after constructor has
411 * finished, and will never be {@code null}.
412 *
413 * @hide
414 */
415 public CharSequence getFormat() {
416 return mFormat;
417 }
418
419 /**
Romain Guy3d1728c2012-10-31 20:31:58 -0700420 * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
421 * depending on whether the user has selected 24-hour format.
Elliott Hughescdafd372013-03-18 17:21:33 -0700422 *
Romain Guy3d1728c2012-10-31 20:31:58 -0700423 * @param handleTicker true if calling this method should schedule/unschedule the
424 * time ticker, false otherwise
425 */
426 private void chooseFormat(boolean handleTicker) {
427 final boolean format24Requested = is24HourModeEnabled();
428
Elliott Hughescdafd372013-03-18 17:21:33 -0700429 LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
430
Romain Guy3d1728c2012-10-31 20:31:58 -0700431 if (format24Requested) {
Elliott Hughescdafd372013-03-18 17:21:33 -0700432 mFormat = abc(mFormat24, mFormat12, ld.timeFormat24);
Romain Guy3d1728c2012-10-31 20:31:58 -0700433 } else {
Elliott Hughescdafd372013-03-18 17:21:33 -0700434 mFormat = abc(mFormat12, mFormat24, ld.timeFormat12);
Romain Guy3d1728c2012-10-31 20:31:58 -0700435 }
436
437 boolean hadSeconds = mHasSeconds;
438 mHasSeconds = DateFormat.hasSeconds(mFormat);
439
Romain Guya76f7db2012-11-06 17:35:23 -0800440 if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
441 if (hadSeconds) getHandler().removeCallbacks(mTicker);
442 else mTicker.run();
Romain Guy3d1728c2012-10-31 20:31:58 -0700443 }
444 }
445
446 /**
447 * Returns a if not null, else return b if not null, else return c.
448 */
449 private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) {
450 return a == null ? (b == null ? c : b) : a;
451 }
452
453 @Override
454 protected void onAttachedToWindow() {
455 super.onAttachedToWindow();
456
457 if (!mAttached) {
458 mAttached = true;
459
460 registerReceiver();
461 registerObserver();
462
463 createTime(mTimeZone);
464
465 if (mHasSeconds) {
466 mTicker.run();
467 } else {
468 onTimeChanged();
469 }
470 }
471 }
472
473 @Override
474 protected void onDetachedFromWindow() {
475 super.onDetachedFromWindow();
476
477 if (mAttached) {
478 unregisterReceiver();
479 unregisterObserver();
480
481 getHandler().removeCallbacks(mTicker);
482
483 mAttached = false;
484 }
485 }
486
487 private void registerReceiver() {
488 final IntentFilter filter = new IntentFilter();
489
490 filter.addAction(Intent.ACTION_TIME_TICK);
491 filter.addAction(Intent.ACTION_TIME_CHANGED);
492 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
493
494 getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
495 }
496
497 private void registerObserver() {
498 final ContentResolver resolver = getContext().getContentResolver();
499 resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
500 }
501
502 private void unregisterReceiver() {
503 getContext().unregisterReceiver(mIntentReceiver);
504 }
505
506 private void unregisterObserver() {
507 final ContentResolver resolver = getContext().getContentResolver();
508 resolver.unregisterContentObserver(mFormatChangeObserver);
509 }
510
511 private void onTimeChanged() {
512 mTime.setTimeInMillis(System.currentTimeMillis());
513 setText(DateFormat.format(mFormat, mTime));
514 }
515}