13d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy/* 23d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Copyright (C) 2012 The Android Open Source Project 33d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 43d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 53d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * you may not use this file except in compliance with the License. 63d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * You may obtain a copy of the License at 73d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 83d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * http://www.apache.org/licenses/LICENSE-2.0 93d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Unless required by applicable law or agreed to in writing, software 113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * distributed under the License is distributed on an "AS IS" BASIS, 123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * See the License for the specific language governing permissions and 143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * limitations under the License. 153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guypackage android.widget; 183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.annotation.NonNull; 209c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinekimport android.app.ActivityManager; 213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.BroadcastReceiver; 223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.ContentResolver; 233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.Context; 243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.Intent; 253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.IntentFilter; 263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.res.TypedArray; 273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.database.ContentObserver; 283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.net.Uri; 293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.os.Handler; 303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.os.SystemClock; 319c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinekimport android.os.UserHandle; 323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.provider.Settings; 333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.text.format.DateFormat; 343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.util.AttributeSet; 35a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guyimport android.view.RemotableViewMethod; 3694a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.view.ViewHierarchyEncoder; 373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport com.android.internal.R; 393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport java.util.Calendar; 413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport java.util.TimeZone; 423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 43cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughesimport libcore.icu.LocaleData; 44cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes 453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport static android.view.ViewDebug.ExportedProperty; 463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport static android.widget.RemoteViews.*; 473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy/** 493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p><code>TextClock</code> can display the current date and/or time as 503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * a formatted string.</p> 51cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>This view honors the 24-hour format system setting. As such, it is 533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * possible and recommended to provide two different formatting patterns: 543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * one to display the date/time in 24-hour mode and one to display the 55cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * date/time in 12-hour mode. Most callers will want to use the defaults, 56cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * though, which will be appropriate for the user's locale.</p> 57cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>It is possible to determine whether the system is currently in 593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 24-hour mode by calling {@link #is24HourModeEnabled()}.</p> 60cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>The rules used by this widget to decide how to format the date and 623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * time are the following:</p> 633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <ul> 643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>In 24-hour mode: 653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <ul> 663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li> 673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li> 68cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code h:mm a}</li> 693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </ul> 703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </li> 713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>In 12-hour mode: 723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <ul> 733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li> 743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li> 75cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * <li>Otherwise, use a default value appropriate for the user's locale, such as {@code HH:mm}</li> 763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </ul> 773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </li> 783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </ul> 79cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>The {@link CharSequence} instances used as formatting patterns when calling either 813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can 82cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * contain styling information. To do so, use a {@link android.text.Spanned} object. 83cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * Note that if you customize these strings, it is your responsibility to supply strings 84cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * appropriate for formatting dates and/or times in the user's locale.</p> 85cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format12Hour 873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format24Hour 883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_timeZone 893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy@RemoteView 913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guypublic class TextClock extends TextView { 923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 93cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * The default formatting pattern in 12-hour mode. This pattern is used 943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * if {@link #setFormat12Hour(CharSequence)} is called with a null pattern 953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * or if no pattern was specified when creating an instance of this class. 96cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * This default pattern shows only the time, hours and minutes, and an am/pm 983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * indicator. 993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 1003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #setFormat12Hour(CharSequence) 1013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #getFormat12Hour() 10209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * 103cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @deprecated Let the system use locale-appropriate defaults instead. 1043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 105cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm a"; 1063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 108cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * The default formatting pattern in 24-hour mode. This pattern is used 1093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * if {@link #setFormat24Hour(CharSequence)} is called with a null pattern 1103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * or if no pattern was specified when creating an instance of this class. 1113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 1123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * This default pattern shows only the time, hours and minutes. 113cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 114cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #setFormat24Hour(CharSequence) 115cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #getFormat24Hour() 11609b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * 117cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @deprecated Let the system use locale-appropriate defaults instead. 1183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 119cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes public static final CharSequence DEFAULT_FORMAT_24_HOUR = "H:mm"; 1203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 121cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes private CharSequence mFormat12; 122cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes private CharSequence mFormat24; 12325ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler private CharSequence mDescFormat12; 12425ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler private CharSequence mDescFormat24; 1253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @ExportedProperty 1273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private CharSequence mFormat; 1283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @ExportedProperty 1293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private boolean mHasSeconds; 1303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 13125ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler private CharSequence mDescFormat; 13225ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler 133e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer private boolean mRegistered; 1343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private Calendar mTime; 1363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private String mTimeZone; 1373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1389c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek private boolean mShowCurrentUserTime; 1399c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek 140d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck private ContentObserver mFormatChangeObserver; 141d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck private class FormatChangeObserver extends ContentObserver { 142d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck 143d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck public FormatChangeObserver(Handler handler) { 144d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck super(handler); 145d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck } 146d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck 1473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @Override 1483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void onChange(boolean selfChange) { 1493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(); 1503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 1513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 1523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @Override 1543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void onChange(boolean selfChange, Uri uri) { 1553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(); 1563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 1573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 1583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy }; 1593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 1613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @Override 1623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void onReceive(Context context, Intent intent) { 163a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { 164a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy final String timeZone = intent.getStringExtra("time-zone"); 165a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy createTime(timeZone); 1663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 167a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy onTimeChanged(); 1683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 1693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy }; 1703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private final Runnable mTicker = new Runnable() { 1723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void run() { 1733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 1743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy long now = SystemClock.uptimeMillis(); 1763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy long next = now + (1000 - now % 1000); 1773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy getHandler().postAtTime(mTicker, next); 1793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 1803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy }; 1813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 18309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * Creates a new clock using the default patterns for the current locale. 184cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 1853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param context The Context the view is running in, through which it can 1863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * access the current theme, resources, etc. 1873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 1883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @SuppressWarnings("UnusedDeclaration") 1893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public TextClock(Context context) { 1903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy super(context); 1913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy init(); 1923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 1933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 1943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 1953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Creates a new clock inflated from XML. This object's properties are 1963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * intialized from the attributes specified in XML. 197cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 1983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * This constructor uses a default style of 0, so the only attribute values 1993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * applied are those in the Context's Theme and the given AttributeSet. 2003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 2013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param context The Context the view is running in, through which it can 2023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * access the current theme, resources, etc. 2033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param attrs The attributes of the XML tag that is inflating the view 2043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 2053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @SuppressWarnings("UnusedDeclaration") 2063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public TextClock(Context context, AttributeSet attrs) { 2073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy this(context, attrs, 0); 2083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 2113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Creates a new clock inflated from XML. This object's properties are 2123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * intialized from the attributes specified in XML. 2133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 2143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param context The Context the view is running in, through which it can 2153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * access the current theme, resources, etc. 2163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param attrs The attributes of the XML tag that is inflating the view 217617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 218617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * reference to a style resource that supplies default values for 219617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * the view. Can be 0 to not look for defaults. 2203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 221617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public TextClock(Context context, AttributeSet attrs, int defStyleAttr) { 222617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 223617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 224617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 225617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public TextClock(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 226617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 2273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 228617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 229617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette attrs, R.styleable.TextClock, defStyleAttr, defStyleRes); 2303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy try { 231cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes mFormat12 = a.getText(R.styleable.TextClock_format12Hour); 232cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes mFormat24 = a.getText(R.styleable.TextClock_format24Hour); 2333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTimeZone = a.getString(R.styleable.TextClock_timeZone); 2343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } finally { 2353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy a.recycle(); 2363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy init(); 2393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void init() { 242cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes if (mFormat12 == null || mFormat24 == null) { 243cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale); 244cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes if (mFormat12 == null) { 245f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes mFormat12 = ld.timeFormat_hm; 246cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes } 247cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes if (mFormat24 == null) { 248f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes mFormat24 = ld.timeFormat_Hm; 249cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes } 250cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes } 251cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes 2523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy createTime(mTimeZone); 253e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer // Wait until registering for events to handle the ticker 2543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(false); 2553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void createTime(String timeZone) { 2583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy if (timeZone != null) { 2593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone)); 2603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } else { 2613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTime = Calendar.getInstance(); 2623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 2663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Returns the formatting pattern used to display the date and/or time 2673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * in 12-hour mode. The formatting pattern syntax is described in 2683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * {@link DateFormat}. 269cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 2703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @return A {@link CharSequence} or null. 271cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 272cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #setFormat12Hour(CharSequence) 273cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #is24HourModeEnabled() 2743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 2753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @ExportedProperty 2763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public CharSequence getFormat12Hour() { 2773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy return mFormat12; 2783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 2793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 2803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 28109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p>Specifies the formatting pattern used to display the date and/or time 2823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * in 12-hour mode. The formatting pattern syntax is described in 28309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * {@link DateFormat}.</p> 2843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 28509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used 2863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns 28709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * are set to null, the default pattern for the current locale will be used 28809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * instead.</p> 28909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * 29009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p><strong>Note:</strong> if styling is not needed, it is highly recommended 29109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * you supply a format string generated by 29209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method 29309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * takes care of generating a format string adapted to the desired locale.</p> 29409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * 2953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 2963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param format A date/time formatting pattern as described in {@link DateFormat} 297cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 2983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #getFormat12Hour() 2993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #is24HourModeEnabled() 30009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * @see DateFormat#getBestDateTimePattern(java.util.Locale, String) 3013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see DateFormat 302cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 3033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format12Hour 3043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 305a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy @RemotableViewMethod 3063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void setFormat12Hour(CharSequence format) { 3073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mFormat12 = format; 3083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 3093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(); 3103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 3113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 3123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 3133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 31425ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler * Like setFormat12Hour, but for the content description. 31525ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler * @hide 31625ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler */ 31725ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler public void setContentDescriptionFormat12Hour(CharSequence format) { 31825ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler mDescFormat12 = format; 31925ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler 32025ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler chooseFormat(); 32125ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler onTimeChanged(); 32225ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler } 32325ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler 32425ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler /** 3253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Returns the formatting pattern used to display the date and/or time 3263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * in 24-hour mode. The formatting pattern syntax is described in 3273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * {@link DateFormat}. 3283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 3293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @return A {@link CharSequence} or null. 3303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 3313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #setFormat24Hour(CharSequence) 3323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #is24HourModeEnabled() 3333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 3343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @ExportedProperty 3353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public CharSequence getFormat24Hour() { 3363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy return mFormat24; 3373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 3383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 3393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 34009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p>Specifies the formatting pattern used to display the date and/or time 3413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * in 24-hour mode. The formatting pattern syntax is described in 34209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * {@link DateFormat}.</p> 34309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * 34409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used 34509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns 34609b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * are set to null, the default pattern for the current locale will be used 34709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * instead.</p> 348cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 34909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * <p><strong>Note:</strong> if styling is not needed, it is highly recommended 35009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * you supply a format string generated by 35109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method 35209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * takes care of generating a format string adapted to the desired locale.</p> 3533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 3543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param format A date/time formatting pattern as described in {@link DateFormat} 3553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 3563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #getFormat24Hour() 357cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #is24HourModeEnabled() 35809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * @see DateFormat#getBestDateTimePattern(java.util.Locale, String) 3593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see DateFormat 3603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 3613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format24Hour 3623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 363a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy @RemotableViewMethod 3643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void setFormat24Hour(CharSequence format) { 3653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mFormat24 = format; 3663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 3673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(); 3683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 3693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 3703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 3713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 37225ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler * Like setFormat24Hour, but for the content description. 37325ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler * @hide 37425ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler */ 37525ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler public void setContentDescriptionFormat24Hour(CharSequence format) { 37625ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler mDescFormat24 = format; 37725ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler 37825ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler chooseFormat(); 37925ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler onTimeChanged(); 38025ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler } 38125ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler 38225ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler /** 3839c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek * Sets whether this clock should always track the current user and not the user of the 3849c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek * current process. This is used for single instance processes like the systemUI who need 3859c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek * to display time for different users. 3869c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek * 3879c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek * @hide 3889c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek */ 3899c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek public void setShowCurrentUserTime(boolean showCurrentUserTime) { 3909c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek mShowCurrentUserTime = showCurrentUserTime; 3919c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek 3929c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek chooseFormat(); 3939c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek onTimeChanged(); 3949c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek unregisterObserver(); 3959c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek registerObserver(); 3969c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek } 3979c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek 3989c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek /** 3993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Indicates whether the system is currently using the 24-hour mode. 400cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * When the system is in 24-hour mode, this view will use the pattern 4023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern 4033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * returned by {@link #getFormat12Hour()} is used instead. 404cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * If either one of the formats is null, the other format is used. If 40609b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy * both formats are null, the default formats for the current locale are used. 407cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @return true if time should be displayed in 24-hour format, false if it 4093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * should be displayed in 12-hour format. 410cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #setFormat12Hour(CharSequence) 412cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #getFormat12Hour() 4133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #setFormat24Hour(CharSequence) 414cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #getFormat24Hour() 4153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 4163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public boolean is24HourModeEnabled() { 4179c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek if (mShowCurrentUserTime) { 4189c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek return DateFormat.is24HourFormat(getContext(), ActivityManager.getCurrentUser()); 4199c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek } else { 4209c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek return DateFormat.is24HourFormat(getContext()); 4219c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek } 4223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 4233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 4243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 4253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Indicates which time zone is currently used by this view. 426cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @return The ID of the current time zone or null if the default time zone, 4283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * as set by the user, must be used 4293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 4303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see TimeZone 4313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see java.util.TimeZone#getAvailableIDs() 432cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * @see #setTimeZone(String) 4333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 4343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public String getTimeZone() { 4353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy return mTimeZone; 4363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 4373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 4383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 4393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Sets the specified time zone to use in this clock. When the time zone 4403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * is set through this method, system time zone changes (when the user 4413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * sets the time zone in settings for instance) will be ignored. 4423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 4433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param timeZone The desired time zone's ID as specified in {@link TimeZone} 4443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * or null to user the time zone specified by the user 4453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * (system time zone) 4463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 4473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see #getTimeZone() 4483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see java.util.TimeZone#getAvailableIDs() 4493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @see TimeZone#getTimeZone(String) 4503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 4513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_timeZone 4523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 453a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy @RemotableViewMethod 4543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy public void setTimeZone(String timeZone) { 4553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTimeZone = timeZone; 4563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 4573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy createTime(timeZone); 4583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 4593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 4603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 4613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 4623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()} 4633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * depending on whether the user has selected 24-hour format. 464cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Calling this method does not schedule or unschedule the time ticker. 4663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 4673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void chooseFormat() { 4683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy chooseFormat(true); 4693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 4703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 4713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 47206c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey * Returns the current format string. Always valid after constructor has 47306c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey * finished, and will never be {@code null}. 47406c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey * 47506c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey * @hide 47606c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey */ 47706c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey public CharSequence getFormat() { 47806c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey return mFormat; 47906c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey } 48006c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey 48106c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey /** 4823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()} 4833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * depending on whether the user has selected 24-hour format. 484cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * 4853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @param handleTicker true if calling this method should schedule/unschedule the 4863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * time ticker, false otherwise 4873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 4883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void chooseFormat(boolean handleTicker) { 4893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy final boolean format24Requested = is24HourModeEnabled(); 4903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 491cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale); 492cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes 4933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy if (format24Requested) { 494f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes mFormat = abc(mFormat24, mFormat12, ld.timeFormat_Hm); 49525ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler mDescFormat = abc(mDescFormat24, mDescFormat12, mFormat); 4963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } else { 497f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes mFormat = abc(mFormat12, mFormat24, ld.timeFormat_hm); 49825ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler mDescFormat = abc(mDescFormat12, mDescFormat24, mFormat); 4993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy boolean hadSeconds = mHasSeconds; 5023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mHasSeconds = DateFormat.hasSeconds(mFormat); 5033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 504e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer if (handleTicker && mRegistered && hadSeconds != mHasSeconds) { 505a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy if (hadSeconds) getHandler().removeCallbacks(mTicker); 506a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy else mTicker.run(); 5073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy /** 5113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * Returns a if not null, else return b if not null, else return c. 5123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */ 5133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) { 5143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy return a == null ? (b == null ? c : b) : a; 5153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy @Override 518e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer public void onVisibilityAggregated(boolean isVisible) { 519e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer if (!mRegistered && isVisible) { 520e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer mRegistered = true; 5213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy registerReceiver(); 5233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy registerObserver(); 5243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy createTime(mTimeZone); 5263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy if (mHasSeconds) { 5283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTicker.run(); 5293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } else { 5303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy onTimeChanged(); 5313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 532e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer } else if (mRegistered && !isVisible) { 5333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy unregisterReceiver(); 5343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy unregisterObserver(); 5353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy getHandler().removeCallbacks(mTicker); 5373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 538e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer mRegistered = false; 5393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void registerReceiver() { 5433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy final IntentFilter filter = new IntentFilter(); 5443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy filter.addAction(Intent.ACTION_TIME_TICK); 5463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy filter.addAction(Intent.ACTION_TIME_CHANGED); 5473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 5483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5495a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // OK, this is gross but needed. This class is supported by the 5505a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // remote views mechanism and as a part of that the remote views 5515a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // can be inflated by a context for another user without the app 5525a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // having interact users permission - just for loading resources. 5535a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // For example, when adding widgets from a managed profile to the 5545a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // home screen. Therefore, we register the receiver as the user 5555a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi // the app is running as not the one the context is for. 5565a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi getContext().registerReceiverAsUser(mIntentReceiver, android.os.Process.myUserHandle(), 5575a33106d7eb1a7fd22eaa6bdaace25aa09af7b61Oleksandr Peletskyi filter, null, getHandler()); 5583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void registerObserver() { 561e12cd3bb3b855a8c51273d11a6ca14f829bb27bdErik Wolsheimer if (mRegistered) { 562d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck if (mFormatChangeObserver == null) { 563d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck mFormatChangeObserver = new FormatChangeObserver(getHandler()); 564d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck } 565d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck final ContentResolver resolver = getContext().getContentResolver(); 566d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck if (mShowCurrentUserTime) { 567d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck resolver.registerContentObserver(Settings.System.CONTENT_URI, true, 568d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck mFormatChangeObserver, UserHandle.USER_ALL); 569d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck } else { 570d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck resolver.registerContentObserver(Settings.System.CONTENT_URI, true, 571d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck mFormatChangeObserver); 572d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck } 5739c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek } 5743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void unregisterReceiver() { 5773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy getContext().unregisterReceiver(mIntentReceiver); 5783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void unregisterObserver() { 581d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck if (mFormatChangeObserver != null) { 582d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck final ContentResolver resolver = getContext().getContentResolver(); 583d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck resolver.unregisterContentObserver(mFormatChangeObserver); 584d0374c6b25c3ad8e638827bd8190553f80d9bf22John Reck } 5853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 5863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy 5873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy private void onTimeChanged() { 5883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy mTime.setTimeInMillis(System.currentTimeMillis()); 5893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy setText(DateFormat.format(mFormat, mTime)); 59025ffc7ad950d9b2857abe9cb66ed53aed7a18ecfDan Sandler setContentDescription(DateFormat.format(mDescFormat, mTime)); 5913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy } 59294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 59394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy /** @hide */ 59494a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy @Override 59594a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 59694a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy super.encodeProperties(stream); 59794a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 59894a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy CharSequence s = getFormat12Hour(); 59994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("format12Hour", s == null ? null : s.toString()); 60094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 60194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy s = getFormat24Hour(); 60294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("format24Hour", s == null ? null : s.toString()); 60394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("format", mFormat == null ? null : mFormat.toString()); 60494a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy stream.addProperty("hasSeconds", mHasSeconds); 60594a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy } 6063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy} 607