1c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato/*
2c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * Copyright (C) 2010 The Android Open Source Project
3c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato *
4c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License");
5c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * you may not use this file except in compliance with the License.
6c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * You may obtain a copy of the License at
7c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato *
8c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato *      http://www.apache.org/licenses/LICENSE-2.0
9c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato *
10c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * Unless required by applicable law or agreed to in writing, software
11c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS,
12c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * See the License for the specific language governing permissions and
14c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * limitations under the License.
15c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato */
16c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
17c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratopackage android.widget;
18c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
19c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.content.Context;
20c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.content.Intent;
21c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.content.IntentFilter;
22c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.content.BroadcastReceiver;
23c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.database.ContentObserver;
24c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.net.Uri;
25c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.os.Handler;
26c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.text.format.Time;
27c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.util.AttributeSet;
28c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.util.Log;
29c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.provider.Settings;
30c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.provider.Settings.SettingNotFoundException;
31c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.widget.TextView;
32c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport android.widget.RemoteViews.RemoteView;
33c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
34c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport com.android.internal.R;
35c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
36c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport java.text.DateFormat;
37c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport java.text.SimpleDateFormat;
38c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratoimport java.util.Date;
39c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
40c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato//
41c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato// TODO
42c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato// - listen for the next threshold time to update the view.
43c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato// - listen for date format pref changed
44c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato// - put the AM/PM in a smaller font
45c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato//
46c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
47c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato/**
48c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * Displays a given time in a convenient human-readable foramt.
49c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato *
50c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato * @hide
51c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato */
52c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato@RemoteView
53c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onoratopublic class DateTimeView extends TextView {
54c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private static final String TAG = "DateTimeView";
55c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
56c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private static final long TWELVE_HOURS_IN_MINUTES = 12 * 60;
57c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private static final long TWENTY_FOUR_HOURS_IN_MILLIS = 24 * 60 * 60 * 1000;
58c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
59c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private static final int SHOW_TIME = 0;
60c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private static final int SHOW_MONTH_DAY_YEAR = 1;
61c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
62c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    Date mTime;
63c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    long mTimeMillis;
64c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
65c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    int mLastDisplay = -1;
66c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    DateFormat mLastFormat;
67c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
68c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private boolean mAttachedToWindow;
69c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private long mUpdateTimeMillis;
70c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
71c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    public DateTimeView(Context context) {
72c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        super(context);
73c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
74c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
75c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    public DateTimeView(Context context, AttributeSet attrs) {
76c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        super(context, attrs);
77c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
78c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
79c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    @Override
80c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    protected void onAttachedToWindow() {
81c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        super.onDetachedFromWindow();
82c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        registerReceivers();
83c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        mAttachedToWindow = true;
84c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
85c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
86c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    @Override
87c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    protected void onDetachedFromWindow() {
88c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        super.onDetachedFromWindow();
89c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        unregisterReceivers();
90c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        mAttachedToWindow = false;
91c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
92c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
93c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    @android.view.RemotableViewMethod
94c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    public void setTime(long time) {
95c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Time t = new Time();
96c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.set(time);
97c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.second = 0;
98c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        mTimeMillis = t.toMillis(false);
99c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0);
100c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        update();
101c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
102c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
103c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    void update() {
104c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        if (mTime == null) {
105c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            return;
106c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
107c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
108c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long start = System.nanoTime();
109c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
110c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        int display;
111c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Date time = mTime;
112c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
113c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Time t = new Time();
114c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.set(mTimeMillis);
115c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.second = 0;
116c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
117c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.hour -= 12;
118c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long twelveHoursBefore = t.toMillis(false);
119c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.hour += 12;
120c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long twelveHoursAfter = t.toMillis(false);
121c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.hour = 0;
122c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.minute = 0;
123c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long midnightBefore = t.toMillis(false);
124c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.monthDay++;
125c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long midnightAfter = t.toMillis(false);
126c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
127c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long nowMillis = System.currentTimeMillis();
128c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.set(nowMillis);
129c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        t.second = 0;
130c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        nowMillis = t.normalize(false);
131c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
132c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        // Choose the display mode
133c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        choose_display: {
134c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            if ((nowMillis >= midnightBefore && nowMillis < midnightAfter)
135c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    || (nowMillis >= twelveHoursBefore && nowMillis < twelveHoursAfter)) {
136c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                display = SHOW_TIME;
137c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                break choose_display;
138c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            }
139c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            // Else, show month day and year.
140c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            display = SHOW_MONTH_DAY_YEAR;
141c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            break choose_display;
142c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
143c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
144c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        // Choose the format
145c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        DateFormat format;
146c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        if (display == mLastDisplay && mLastFormat != null) {
147c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            // use cached format
148c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            format = mLastFormat;
149c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        } else {
150c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            switch (display) {
151c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                case SHOW_TIME:
152c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    format = getTimeFormat();
153c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    break;
154c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                case SHOW_MONTH_DAY_YEAR:
155c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    format = getDateFormat();
156c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    break;
157c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                default:
158c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    throw new RuntimeException("unknown display value: " + display);
159c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            }
160c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            mLastFormat = format;
161c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
162c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
163c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        // Set the text
164c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        String text = format.format(mTime);
165c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        setText(text);
166c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
167c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        // Schedule the next update
168c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        if (display == SHOW_TIME) {
169c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            // Currently showing the time, update at the later of twelve hours after or midnight.
170c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter;
171c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        } else {
172c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            // Currently showing the date
173c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            if (mTimeMillis < nowMillis) {
174c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                // If the time is in the past, don't schedule an update
175c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                mUpdateTimeMillis = 0;
176c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            } else {
177c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                // If hte time is in the future, schedule one at the earlier of twelve hours
178c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                // before or midnight before.
179c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                mUpdateTimeMillis = twelveHoursBefore < midnightBefore
180c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                        ? twelveHoursBefore : midnightBefore;
181c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            }
182c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
183c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        if (false) {
184c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            Log.d(TAG, "update needed for '" + time + "' at '" + new Date(mUpdateTimeMillis)
185c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    + "' - text=" + text);
186c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
187c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
188c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        long finish = System.nanoTime();
189c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
190c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
191c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private DateFormat getTimeFormat() {
192c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        int res;
193c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Context context = getContext();
194c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        if (android.text.format.DateFormat.is24HourFormat(context)) {
195c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            res = R.string.twenty_four_hour_time_format;
196c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        } else {
197c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            res = R.string.twelve_hour_time_format;
198c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
199c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        String format = context.getString(res);
200c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        return new SimpleDateFormat(format);
201c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
202c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
203c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private DateFormat getDateFormat() {
204c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        String format = Settings.System.getString(getContext().getContentResolver(),
205c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                Settings.System.DATE_FORMAT);
2067747210426f0169b7f10f47a66d15a754b36d64cJoe Onorato        if (format == null || "".equals(format)) {
207c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            return DateFormat.getDateInstance(DateFormat.SHORT);
208c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        } else {
209f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell            try {
210f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell                return new SimpleDateFormat(format);
211f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell            } catch (IllegalArgumentException e) {
212f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell                // If we tried to use a bad format string, fall back to a default.
213f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell                return DateFormat.getDateInstance(DateFormat.SHORT);
214f3311c940aee73afb0eeeedde4799e45f544dbc3Adam Powell            }
215c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
216c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
217c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
218c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private void registerReceivers() {
219c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Context context = getContext();
220c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
221c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        IntentFilter filter = new IntentFilter();
222c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        filter.addAction(Intent.ACTION_TIME_TICK);
223c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        filter.addAction(Intent.ACTION_TIME_CHANGED);
224c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
225c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
226c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        context.registerReceiver(mBroadcastReceiver, filter);
227c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
228c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Uri uri = Settings.System.getUriFor(Settings.System.DATE_FORMAT);
229c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        context.getContentResolver().registerContentObserver(uri, true, mContentObserver);
230c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
231c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
232c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private void unregisterReceivers() {
233c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        Context context = getContext();
234c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        context.unregisterReceiver(mBroadcastReceiver);
235c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        context.getContentResolver().unregisterContentObserver(mContentObserver);
236c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    }
237c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
238c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
239c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        @Override
240c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        public void onReceive(Context context, Intent intent) {
241c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            String action = intent.getAction();
242c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            if (Intent.ACTION_TIME_TICK.equals(action)) {
243c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                if (System.currentTimeMillis() < mUpdateTimeMillis) {
244c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    // The update() function takes a few milliseconds to run because of
245c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    // all of the time conversions it needs to do, so we can't do that
246c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    // every minute.
247c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                    return;
248c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato                }
249c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            }
250c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            // ACTION_TIME_CHANGED can also signal a change of 12/24 hr. format.
251c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            mLastFormat = null;
252c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            update();
253c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
254c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    };
255c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato
256c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    private ContentObserver mContentObserver = new ContentObserver(new Handler()) {
257c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        @Override
258c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        public void onChange(boolean selfChange) {
259c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            mLastFormat = null;
260c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato            update();
261c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato        }
262c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato    };
263c83bb730ec0333e52990a40edf6d54bb66b1d5baJoe Onorato}
264