TextClock.java revision f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6c
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
193d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.BroadcastReceiver;
203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.ContentResolver;
213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.Context;
223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.Intent;
233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.IntentFilter;
243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.content.res.TypedArray;
253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.database.ContentObserver;
263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.net.Uri;
273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.os.Handler;
283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.os.SystemClock;
293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.provider.Settings;
303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.text.format.DateFormat;
313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport android.util.AttributeSet;
32a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guyimport android.view.RemotableViewMethod;
333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport com.android.internal.R;
353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport java.util.Calendar;
373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport java.util.TimeZone;
383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
39cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughesimport libcore.icu.LocaleData;
40cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes
413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport static android.view.ViewDebug.ExportedProperty;
423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guyimport static android.widget.RemoteViews.*;
433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy/**
453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p><code>TextClock</code> can display the current date and/or time as
463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * a formatted string.</p>
47cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *
483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>This view honors the 24-hour format system setting. As such, it is
493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * possible and recommended to provide two different formatting patterns:
503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * one to display the date/time in 24-hour mode and one to display the
51cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * date/time in 12-hour mode. Most callers will want to use the defaults,
52cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * though, which will be appropriate for the user's locale.</p>
53cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *
543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>It is possible to determine whether the system is currently in
553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * 24-hour mode by calling {@link #is24HourModeEnabled()}.</p>
56cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *
573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>The rules used by this widget to decide how to format the date and
583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * time are the following:</p>
593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <ul>
603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *     <li>In 24-hour mode:
613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *         <ul>
623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *             <li>Use the value returned by {@link #getFormat24Hour()} when non-null</li>
633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *             <li>Otherwise, use the value returned by {@link #getFormat12Hour()} when non-null</li>
64cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *             <li>Otherwise, use a default value appropriate for the user's locale, such as {@code h:mm a}</li>
653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *         </ul>
663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *     </li>
673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *     <li>In 12-hour mode:
683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *         <ul>
693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *             <li>Use the value returned by {@link #getFormat12Hour()} when non-null</li>
703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *             <li>Otherwise, use the value returned by {@link #getFormat24Hour()} when non-null</li>
71cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *             <li>Otherwise, use a default value appropriate for the user's locale, such as {@code HH:mm}</li>
723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *         </ul>
733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy *     </li>
743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * </ul>
75cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *
763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * <p>The {@link CharSequence} instances used as formatting patterns when calling either
773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * {@link #setFormat24Hour(CharSequence)} or {@link #setFormat12Hour(CharSequence)} can
78cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * contain styling information. To do so, use a {@link android.text.Spanned} object.
79cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * Note that if you customize these strings, it is your responsibility to supply strings
80cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes * appropriate for formatting dates and/or times in the user's locale.</p>
81cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes *
823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format12Hour
833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_format24Hour
843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy * @attr ref android.R.styleable#TextClock_timeZone
853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy */
863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy@RemoteView
873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guypublic class TextClock extends TextView {
883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
89cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * The default formatting pattern in 12-hour mode. This pattern is used
903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * if {@link #setFormat12Hour(CharSequence)} is called with a null pattern
913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * or if no pattern was specified when creating an instance of this class.
92cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * This default pattern shows only the time, hours and minutes, and an am/pm
943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * indicator.
953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat12Hour(CharSequence)
973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getFormat12Hour()
9809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
99cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @deprecated Let the system use locale-appropriate defaults instead.
1003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
101cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes    public static final CharSequence DEFAULT_FORMAT_12_HOUR = "h:mm a";
1023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
104cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * The default formatting pattern in 24-hour mode. This pattern is used
1053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * if {@link #setFormat24Hour(CharSequence)} is called with a null pattern
1063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * or if no pattern was specified when creating an instance of this class.
1073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
1083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * This default pattern shows only the time, hours and minutes.
109cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
110cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #setFormat24Hour(CharSequence)
111cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #getFormat24Hour()
11209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
113cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @deprecated Let the system use locale-appropriate defaults instead.
1143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
115cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes    public static final CharSequence DEFAULT_FORMAT_24_HOUR = "H:mm";
1163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
117cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes    private CharSequence mFormat12;
118cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes    private CharSequence mFormat24;
1193d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
1213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private CharSequence mFormat;
1223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
1233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private boolean mHasSeconds;
1243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private boolean mAttached;
1263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private Calendar mTime;
1283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private String mTimeZone;
1293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final ContentObserver mFormatChangeObserver = new ContentObserver(new Handler()) {
1313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onChange(boolean selfChange) {
1333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            chooseFormat();
1343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onChange(boolean selfChange, Uri uri) {
1393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            chooseFormat();
1403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
1453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        @Override
1463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void onReceive(Context context, Intent intent) {
147a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
148a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy                final String timeZone = intent.getStringExtra("time-zone");
149a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy                createTime(timeZone);
1503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            }
151a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            onTimeChanged();
1523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private final Runnable mTicker = new Runnable() {
1563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        public void run() {
1573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            onTimeChanged();
1583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            long now = SystemClock.uptimeMillis();
1603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            long next = now + (1000 - now % 1000);
1613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            getHandler().postAtTime(mTicker, next);
1633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
1643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    };
1653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
16709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * Creates a new clock using the default patterns for the current locale.
168cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
1693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param context The Context the view is running in, through which it can
1703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        access the current theme, resources, etc.
1713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
1723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @SuppressWarnings("UnusedDeclaration")
1733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public TextClock(Context context) {
1743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super(context);
1753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        init();
1763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
1773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
1783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
1793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Creates a new clock inflated from XML. This object's properties are
1803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * intialized from the attributes specified in XML.
181cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
1823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * This constructor uses a default style of 0, so the only attribute values
1833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * applied are those in the Context's Theme and the given AttributeSet.
1843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
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     * @param attrs The attributes of the XML tag that is inflating the view
1883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
1893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @SuppressWarnings("UnusedDeclaration")
1903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public TextClock(Context context, AttributeSet attrs) {
1913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        this(context, attrs, 0);
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.
1973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
1983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param context The Context the view is running in, through which it can
1993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        access the current theme, resources, etc.
2003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param attrs The attributes of the XML tag that is inflating the view
2013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param defStyle The default style to apply to this view. If 0, no style
2023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        will be applied (beyond what is included in the theme). This may
2033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        either be an attribute resource, whose value will be retrieved
2043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *        from the current theme, or an explicit style resource
2053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
2063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public TextClock(Context context, AttributeSet attrs, int defStyle) {
2073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super(context, attrs, defStyle);
2083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextClock, defStyle, 0);
2103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        try {
211cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            mFormat12 = a.getText(R.styleable.TextClock_format12Hour);
212cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            mFormat24 = a.getText(R.styleable.TextClock_format24Hour);
2133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTimeZone = a.getString(R.styleable.TextClock_timeZone);
2143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } finally {
2153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            a.recycle();
2163d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
2173d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2183d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        init();
2193d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void init() {
222cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        if (mFormat12 == null || mFormat24 == null) {
223cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
224cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            if (mFormat12 == null) {
225f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes                mFormat12 = ld.timeFormat_hm;
226cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            }
227cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            if (mFormat24 == null) {
228f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes                mFormat24 = ld.timeFormat_Hm;
229cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes            }
230cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        }
231cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes
2323d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        createTime(mTimeZone);
2333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        // Wait until onAttachedToWindow() to handle the ticker
2343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat(false);
2353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void createTime(String timeZone) {
2383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (timeZone != null) {
2393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTime = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
2403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } else {
2413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mTime = Calendar.getInstance();
2423d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
2433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
2463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns the formatting pattern used to display the date and/or time
2473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 12-hour mode. The formatting pattern syntax is described in
2483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * {@link DateFormat}.
249cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return A {@link CharSequence} or null.
251cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
252cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #setFormat12Hour(CharSequence)
253cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #is24HourModeEnabled()
2543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
2553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
2563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public CharSequence getFormat12Hour() {
2573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mFormat12;
2583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
26109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>Specifies the formatting pattern used to display the date and/or time
2623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 12-hour mode. The formatting pattern syntax is described in
26309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat}.</p>
2643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
26509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
2663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
26709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * are set to null, the default pattern for the current locale will be used
26809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * instead.</p>
26909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
27009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
27109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * you supply a format string generated by
27209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
27309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * takes care of generating a format string adapted to the desired locale.</p>
27409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
2753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
2763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param format A date/time formatting pattern as described in {@link DateFormat}
277cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getFormat12Hour()
2793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #is24HourModeEnabled()
28009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
2813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see DateFormat
282cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
2833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_format12Hour
2843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
285a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
2863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setFormat12Hour(CharSequence format) {
2873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mFormat12 = format;
2883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat();
2903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
2913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
2923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
2933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
2943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns the formatting pattern used to display the date and/or time
2953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 24-hour mode. The formatting pattern syntax is described in
2963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * {@link DateFormat}.
2973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
2983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return A {@link CharSequence} or null.
2993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat24Hour(CharSequence)
3013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #is24HourModeEnabled()
3023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
3033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @ExportedProperty
3043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public CharSequence getFormat24Hour() {
3053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mFormat24;
3063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
30909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>Specifies the formatting pattern used to display the date and/or time
3103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * in 24-hour mode. The formatting pattern syntax is described in
31109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat}.</p>
31209b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     *
31309b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p>If this pattern is set to null, {@link #getFormat24Hour()} will be used
31409b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * even in 12-hour mode. If both 24-hour and 12-hour formatting patterns
31509b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * are set to null, the default pattern for the current locale will be used
31609b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * instead.</p>
317cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
31809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * <p><strong>Note:</strong> if styling is not needed, it is highly recommended
31909b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * you supply a format string generated by
32009b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * {@link DateFormat#getBestDateTimePattern(java.util.Locale, String)}. This method
32109b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * takes care of generating a format string adapted to the desired locale.</p>
3223d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param format A date/time formatting pattern as described in {@link DateFormat}
3243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getFormat24Hour()
326cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #is24HourModeEnabled()
32709b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * @see DateFormat#getBestDateTimePattern(java.util.Locale, String)
3283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see DateFormat
3293d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3303d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_format24Hour
3313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
332a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
3333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setFormat24Hour(CharSequence format) {
3343d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mFormat24 = format;
3353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat();
3373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
3383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3403d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3413d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Indicates whether the system is currently using the 24-hour mode.
342cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * When the system is in 24-hour mode, this view will use the pattern
3443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * returned by {@link #getFormat24Hour()}. In 12-hour mode, the pattern
3453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * returned by {@link #getFormat12Hour()} is used instead.
346cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * If either one of the formats is null, the other format is used. If
34809b1994c4d3c47bfa41374a4d420eb5110b9a48aRomain Guy     * both formats are null, the default formats for the current locale are used.
349cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return true if time should be displayed in 24-hour format, false if it
3513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *         should be displayed in 12-hour format.
352cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat12Hour(CharSequence)
354cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #getFormat12Hour()
3553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #setFormat24Hour(CharSequence)
356cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #getFormat24Hour()
3573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
3583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public boolean is24HourModeEnabled() {
3593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return DateFormat.is24HourFormat(getContext());
3603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Indicates which time zone is currently used by this view.
364cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
3653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @return The ID of the current time zone or null if the default time zone,
3663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *         as set by the user, must be used
3673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see TimeZone
3693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see java.util.TimeZone#getAvailableIDs()
370cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     * @see #setTimeZone(String)
3713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
3723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public String getTimeZone() {
3733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return mTimeZone;
3743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
3773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Sets the specified time zone to use in this clock. When the time zone
3783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * is set through this method, system time zone changes (when the user
3793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * sets the time zone in settings for instance) will be ignored.
3803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param timeZone The desired time zone's ID as specified in {@link TimeZone}
3823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                 or null to user the time zone specified by the user
3833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                 (system time zone)
3843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see #getTimeZone()
3863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see java.util.TimeZone#getAvailableIDs()
3873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @see TimeZone#getTimeZone(String)
3883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *
3893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @attr ref android.R.styleable#TextClock_timeZone
3903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
391a9cfe677eec0324a94509c6a5d29cec5b8a7a7cfRomain Guy    @RemotableViewMethod
3923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    public void setTimeZone(String timeZone) {
3933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mTimeZone = timeZone;
3943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        createTime(timeZone);
3963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        onTimeChanged();
3973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
3983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
3993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
4003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
4013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * depending on whether the user has selected 24-hour format.
402cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
4033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Calling this method does not schedule or unschedule the time ticker.
4043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void chooseFormat() {
4063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        chooseFormat(true);
4073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
41006c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * Returns the current format string. Always valid after constructor has
41106c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * finished, and will never be {@code null}.
41206c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     *
41306c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     * @hide
41406c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey     */
41506c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    public CharSequence getFormat() {
41606c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey        return mFormat;
41706c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    }
41806c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey
41906c5f8a768bcd4f7b6441f7525bd5c639399fc76Jeff Sharkey    /**
4203d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Selects either one of {@link #getFormat12Hour()} or {@link #getFormat24Hour()}
4213d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * depending on whether the user has selected 24-hour format.
422cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes     *
4233d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * @param handleTicker true if calling this method should schedule/unschedule the
4243d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     *                     time ticker, false otherwise
4253d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4263d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void chooseFormat(boolean handleTicker) {
4273d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final boolean format24Requested = is24HourModeEnabled();
4283d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
429cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes        LocaleData ld = LocaleData.get(getContext().getResources().getConfiguration().locale);
430cdafd37f3148dfc6f44f2e5de8b31adb6bf9e476Elliott Hughes
4313d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (format24Requested) {
432f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes            mFormat = abc(mFormat24, mFormat12, ld.timeFormat_Hm);
4333d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        } else {
434f7d5e0a53e168f2acc17b098bdd4b927fa1b1d6cElliott Hughes            mFormat = abc(mFormat12, mFormat24, ld.timeFormat_hm);
4353d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4363d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4373d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        boolean hadSeconds = mHasSeconds;
4383d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mHasSeconds = DateFormat.hasSeconds(mFormat);
4393d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
440a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy        if (handleTicker && mAttached && hadSeconds != mHasSeconds) {
441a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            if (hadSeconds) getHandler().removeCallbacks(mTicker);
442a76f7db323598f78512bbbdf2fb89248c9e317e5Romain Guy            else mTicker.run();
4433d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4443d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4453d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4463d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    /**
4473d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     * Returns a if not null, else return b if not null, else return c.
4483d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy     */
4493d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private static CharSequence abc(CharSequence a, CharSequence b, CharSequence c) {
4503d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        return a == null ? (b == null ? c : b) : a;
4513d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4523d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4533d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @Override
4543d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    protected void onAttachedToWindow() {
4553d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super.onAttachedToWindow();
4563d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4573d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (!mAttached) {
4583d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mAttached = true;
4593d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4603d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            registerReceiver();
4613d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            registerObserver();
4623d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4633d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            createTime(mTimeZone);
4643d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4653d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            if (mHasSeconds) {
4663d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy                mTicker.run();
4673d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            } else {
4683d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy                onTimeChanged();
4693d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            }
4703d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4713d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4723d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4733d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    @Override
4743d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    protected void onDetachedFromWindow() {
4753d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        super.onDetachedFromWindow();
4763d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4773d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        if (mAttached) {
4783d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            unregisterReceiver();
4793d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            unregisterObserver();
4803d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4813d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            getHandler().removeCallbacks(mTicker);
4823d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4833d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy            mAttached = false;
4843d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        }
4853d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4863d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4873d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void registerReceiver() {
4883d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final IntentFilter filter = new IntentFilter();
4893d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4903d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIME_TICK);
4913d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIME_CHANGED);
4923d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
4933d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4943d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        getContext().registerReceiver(mIntentReceiver, filter, null, getHandler());
4953d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
4963d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
4973d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void registerObserver() {
4983d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final ContentResolver resolver = getContext().getContentResolver();
4993d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        resolver.registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);
5003d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5013d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5023d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void unregisterReceiver() {
5033d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        getContext().unregisterReceiver(mIntentReceiver);
5043d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5053d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5063d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void unregisterObserver() {
5073d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        final ContentResolver resolver = getContext().getContentResolver();
5083d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        resolver.unregisterContentObserver(mFormatChangeObserver);
5093d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5103d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy
5113d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    private void onTimeChanged() {
5123d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        mTime.setTimeInMillis(System.currentTimeMillis());
5133d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy        setText(DateFormat.format(mFormat, mTime));
5143d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy    }
5153d1728c03a0cd1aaed6bc81c97de27d62c771a6eRomain Guy}
516