TextClock.java revision 94a6d15ede149189bba9e5f474ed853c98230e75
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;
1233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
1253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private CharSequence mFormat;
1263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
1273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private boolean mHasSeconds;
1283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private boolean mAttached;
1303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private Calendar mTime;
1323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private String mTimeZone;
1333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1349c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek    private boolean mShowCurrentUserTime;
1359c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek
1363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
1373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onChange(boolean selfChange) {
1393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            chooseFormat();
1403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onChange(boolean selfChange, Uri uri) {
1453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            chooseFormat();
1463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
1513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onReceive(Context context, Intent intent) {
153a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
154a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy                final String timeZone = intent.getStringExtra("time-zone");
155a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy                createTime(timeZone);
1563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            }
157a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            onTimeChanged();
1583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final Runnable mTicker = new Runnable() {
1623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void run() {
1633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            long now = SystemClock.uptimeMillis();
1663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            long next = now + (1000 - now % 1000);
1673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            getHandler().postAtTime(mTicker, next);
1693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
17309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * Creates a new clock using the default patterns for the current locale.
174cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
1753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param context The Context the view is running in, through which it can
1763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        access the current theme, resources, etc.
1773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
1783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @SuppressWarnings("UnusedDeclaration")
1793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public TextClock(Context context) {
1803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super(context);
1813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        init();
1823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
1833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
1853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Creates a new clock inflated from XML. This object's properties are
1863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * intialized from the attributes specified in XML.
187cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
1883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * This constructor uses a default style of 0, so the only attribute values
1893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * applied are those in the Context's Theme and the given AttributeSet.
1903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
1913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param context The Context the view is running in, through which it can
1923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        access the current theme, resources, etc.
1933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param attrs The attributes of the XML tag that is inflating the view
1943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
1953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @SuppressWarnings("UnusedDeclaration")
1963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public TextClock(Context context, AttributeSet attrs) {
1973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        this(context, attrs, 0);
1983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
1993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
2013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Creates a new clock inflated from XML. This object's properties are
2023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * intialized from the attributes specified in XML.
2033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
2043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param context The Context the view is running in, through which it can
2053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        access the current theme, resources, etc.
2063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param attrs The attributes of the XML tag that is inflating the view
207617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     * @param defStyleAttr An attribute in the current theme that contains a
208617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        reference to a style resource that supplies default values for
209617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette     *        the view. Can be 0 to not look for defaults.
2103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
211617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public TextClock(Context context, AttributeSet attrs, int defStyleAttr) {
212617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
213617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    }
214617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette
215617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public TextClock(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
216617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
2173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
218617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(
219617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette                attrs, R.styleable.TextClock, defStyleAttr, defStyleRes);
2203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        try {
221cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            mFormat12 = a.getText(R.styleable.TextClock_format12Hour);
222cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            mFormat24 = a.getText(R.styleable.TextClock_format24Hour);
2233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTimeZone = a.getString(R.styleable.TextClock_timeZone);
2243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } finally {
2253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            a.recycle();
2263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
2273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        init();
2293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void init() {
232cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        if (mFormat12 == null || mFormat24 == null) {
233cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
234cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            if (mFormat12 == null) {
235f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes                mFormat12 = ld.timeFormat_hm;
236cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            }
237cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            if (mFormat24 == null) {
238f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes                mFormat24 = ld.timeFormat_Hm;
239cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            }
240cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        }
241cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes
2423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        createTime(mTimeZone);
2433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        // Wait until onAttachedToWindow() to handle the ticker
2443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat(false);
2453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void createTime(String timeZone) {
2483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (timeZone != null) {
2493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
2503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } else {
2513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTime = Calendar.getInstance();
2523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
2533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
2563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns the formatting pattern used to display the date and/or time
2573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 12-hour mode. The formatting pattern syntax is described in
2583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * {@link DateFormat}.
259cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return A {@link CharSequence} or null.
261cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
262cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #setFormat12Hour(CharSequence)
263cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #is24HourModeEnabled()
2643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
2653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
2663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public CharSequence getFormat12Hour() {
2673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mFormat12;
2683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
27109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>Specifies the formatting pattern used to display the date and/or time
2723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 12-hour mode. The formatting pattern syntax is described in
27309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat}.</p>
2743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
27509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
2763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
27709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * are set to null, the default pattern for the current locale will be used
27809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * instead.</p>
27909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
28009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
28109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * you supply a format string generated by
28209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
28309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * takes care of generating a format string adapted to the desired locale.</p>
28409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
2853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
2863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param format A date/time formatting pattern as described in {@link DateFormat}
287cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getFormat12Hour()
2893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #is24HourModeEnabled()
29009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
2913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see DateFormat
292cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_format12Hour
2943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
295a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
2963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setFormat12Hour(CharSequence format) {
2973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mFormat12 = format;
2983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat();
3003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
3013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns the formatting pattern used to display the date and/or time
3053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 24-hour mode. The formatting pattern syntax is described in
3063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * {@link DateFormat}.
3073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return A {@link CharSequence} or null.
3093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat24Hour(CharSequence)
3113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #is24HourModeEnabled()
3123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
3133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
3143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public CharSequence getFormat24Hour() {
3153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mFormat24;
3163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
31909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>Specifies the formatting pattern used to display the date and/or time
3203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 24-hour mode. The formatting pattern syntax is described in
32109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat}.</p>
32209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
32309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
32409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
32509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * are set to null, the default pattern for the current locale will be used
32609b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * instead.</p>
327cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
32809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
32909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * you supply a format string generated by
33009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
33109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * takes care of generating a format string adapted to the desired locale.</p>
3323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param format A date/time formatting pattern as described in {@link DateFormat}
3343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getFormat24Hour()
336cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #is24HourModeEnabled()
33709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
3383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see DateFormat
3393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_format24Hour
3413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
342a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
3433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setFormat24Hour(CharSequence format) {
3443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mFormat24 = format;
3453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat();
3473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
3483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3519c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     * Sets whether this clock should always track the current user and not the user of the
3529c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     * current process. This is used for single instance processes like the systemUI who need
3539c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     * to display time for different users.
3549c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     *
3559c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     * @hide
3569c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek     */
3579c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek    public void setShowCurrentUserTime(boolean showCurrentUserTime) {
3589c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        mShowCurrentUserTime = showCurrentUserTime;
3599c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek
3609c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        chooseFormat();
3619c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        onTimeChanged();
3629c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        unregisterObserver();
3639c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        registerObserver();
3649c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek    }
3659c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek
3669c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek    /**
3673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Indicates whether the system is currently using the 24-hour mode.
368cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * When the system is in 24-hour mode, this view will use the pattern
3703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
3713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * returned by {@link #getFormat12Hour()} is used instead.
372cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * If either one of the formats is null, the other format is used. If
37409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * both formats are null, the default formats for the current locale are used.
375cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return true if time should be displayed in 24-hour format, false if it
3773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *         should be displayed in 12-hour format.
378cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat12Hour(CharSequence)
380cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #getFormat12Hour()
3813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat24Hour(CharSequence)
382cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #getFormat24Hour()
3833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
3843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public boolean is24HourModeEnabled() {
3859c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        if (mShowCurrentUserTime) {
3869c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek            return DateFormat.is24HourFormat(getContext(), ActivityManager.getCurrentUser());
3879c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        } else {
3889c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek            return DateFormat.is24HourFormat(getContext());
3899c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        }
3903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Indicates which time zone is currently used by this view.
394cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return The ID of the current time zone or null if the default time zone,
3963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *         as set by the user, must be used
3973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see TimeZone
3993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see java.util.TimeZone#getAvailableIDs()
400cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #setTimeZone(String)
4013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public String getTimeZone() {
4033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mTimeZone;
4043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
4073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Sets the specified time zone to use in this clock. When the time zone
4083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * is set through this method, system time zone changes (when the user
4093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * sets the time zone in settings for instance) will be ignored.
4103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
4113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param timeZone The desired time zone's ID as specified in {@link TimeZone}
4123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                 or null to user the time zone specified by the user
4133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                 (system time zone)
4143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
4153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getTimeZone()
4163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see java.util.TimeZone#getAvailableIDs()
4173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see TimeZone#getTimeZone(String)
4183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
4193d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_timeZone
4203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
421a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
4223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setTimeZone(String timeZone) {
4233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mTimeZone = timeZone;
4243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        createTime(timeZone);
4263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
4273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
4303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
4313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * depending on whether the user has selected 24-hour format.
432cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
4333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Calling this method does not schedule or unschedule the time ticker.
4343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void chooseFormat() {
4363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat(true);
4373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
44006c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * Returns the current format string. Always valid after constructor has
44106c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * finished, and will never be {@code null}.
44206c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     *
44306c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * @hide
44406c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     */
44506c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    public CharSequence getFormat() {
44606c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey        return mFormat;
44706c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    }
44806c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey
44906c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    /**
4503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
4513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * depending on whether the user has selected 24-hour format.
452cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
4533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param handleTicker true if calling this method should schedule/unschedule the
4543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                     time ticker, false otherwise
4553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void chooseFormat(boolean handleTicker) {
4573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final boolean format24Requested = is24HourModeEnabled();
4583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
459cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
460cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes
4613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (format24Requested) {
462f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes            mFormat = abc(mFormat24, mFormat12, ld.timeFormat_Hm);
4633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } else {
464f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes            mFormat = abc(mFormat12, mFormat24, ld.timeFormat_hm);
4653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        boolean hadSeconds = mHasSeconds;
4683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mHasSeconds = DateFormat.hasSeconds(mFormat);
4693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
470a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy        if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
471a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            if (hadSeconds) getHandler().removeCallbacks(mTicker);
472a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            else mTicker.run();
4733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
4773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns a if not null, else return b if not null, else return c.
4783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) {
4803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return a == null ? (b == null ? c : b) : a;
4813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @Override
4843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    protected void onAttachedToWindow() {
4853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super.onAttachedToWindow();
4863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (!mAttached) {
4883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mAttached = true;
4893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            registerReceiver();
4913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            registerObserver();
4923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            createTime(mTimeZone);
4943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            if (mHasSeconds) {
4963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy                mTicker.run();
4973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            } else {
4983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy                onTimeChanged();
4993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            }
5003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
5013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @Override
5043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    protected void onDetachedFromWindow() {
5053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super.onDetachedFromWindow();
5063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (mAttached) {
5083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            unregisterReceiver();
5093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            unregisterObserver();
5103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            getHandler().removeCallbacks(mTicker);
5123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mAttached = false;
5143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
5153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void registerReceiver() {
5183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final IntentFilter filter = new IntentFilter();
5193d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIME_TICK);
5213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIME_CHANGED);
5223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
5233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
524692356b7c392130b7f38f46a60570617c978ba75Kenny Guy        getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
5253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void registerObserver() {
5283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final ContentResolver resolver = getContext().getContentResolver();
5299c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        if (mShowCurrentUserTime) {
5309c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek            resolver.registerContentObserver(Settings.System.CONTENT_URI, true,
5319c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek                    mFormatChangeObserver, UserHandle.USER_ALL);
5329c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        } else {
5339c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek            resolver.registerContentObserver(Settings.System.CONTENT_URI, true,
5349c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek                    mFormatChangeObserver);
5359c4a707912da2c954b2d3d1311b8a691ded8aa16Selim Cinek        }
5363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void unregisterReceiver() {
5393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        getContext().unregisterReceiver(mIntentReceiver);
5403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void unregisterObserver() {
5433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final ContentResolver resolver = getContext().getContentResolver();
5443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        resolver.unregisterContentObserver(mFormatChangeObserver);
5453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void onTimeChanged() {
5483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mTime.setTimeInMillis(System.currentTimeMillis());
5493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        setText(DateFormat.format(mFormat, mTime));
5503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
55194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy
55294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy    /** @hide */
55394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy    @Override
55494a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
55594a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        super.encodeProperties(stream);
55694a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy
55794a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        CharSequence s = getFormat12Hour();
55894a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        stream.addProperty("format12Hour", s == null ? null : s.toString());
55994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy
56094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        s = getFormat24Hour();
56194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        stream.addProperty("format24Hour", s == null ? null : s.toString());
56294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        stream.addProperty("format", mFormat == null ? null : mFormat.toString());
56394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy        stream.addProperty("hasSeconds", mHasSeconds);
56494a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy    }
5653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy}
566