diff options
author | Joe Onorato <joeo@android.com> | 2010-01-19 16:32:22 -0800 |
---|---|---|
committer | Joe Onorato <joeo@android.com> | 2010-01-19 16:32:22 -0800 |
commit | c83bb730ec0333e52990a40edf6d54bb66b1d5ba (patch) | |
tree | d64faa280ae393891673278b4d61ec274a8e4259 /core/java/android/widget/DateTimeView.java | |
parent | 63ce8e817c9b800b4f08b64c343e533783961b6e (diff) | |
download | frameworks_base-c83bb730ec0333e52990a40edf6d54bb66b1d5ba.zip frameworks_base-c83bb730ec0333e52990a40edf6d54bb66b1d5ba.tar.gz frameworks_base-c83bb730ec0333e52990a40edf6d54bb66b1d5ba.tar.bz2 |
Add DateTimeView, a widget that shows a time or the date depending on the
current time. Use that for notifications instead of a TextView that
doesn't ever update.
BUG 1563917
Diffstat (limited to 'core/java/android/widget/DateTimeView.java')
-rw-r--r-- | core/java/android/widget/DateTimeView.java | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java new file mode 100644 index 0000000..9067e26 --- /dev/null +++ b/core/java/android/widget/DateTimeView.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.widget; + +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.BroadcastReceiver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.text.format.Time; +import android.util.AttributeSet; +import android.util.Log; +import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; +import android.widget.TextView; +import android.widget.RemoteViews.RemoteView; + +import com.android.internal.R; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +// +// TODO +// - listen for the next threshold time to update the view. +// - listen for date format pref changed +// - put the AM/PM in a smaller font +// + +/** + * Displays a given time in a convenient human-readable foramt. + * + * @hide + */ +@RemoteView +public class DateTimeView extends TextView { + private static final String TAG = "DateTimeView"; + + private static final long TWELVE_HOURS_IN_MINUTES = 12 * 60; + private static final long TWENTY_FOUR_HOURS_IN_MILLIS = 24 * 60 * 60 * 1000; + + private static final int SHOW_TIME = 0; + private static final int SHOW_MONTH_DAY_YEAR = 1; + + Date mTime; + long mTimeMillis; + + int mLastDisplay = -1; + DateFormat mLastFormat; + + private boolean mAttachedToWindow; + private long mUpdateTimeMillis; + + public DateTimeView(Context context) { + super(context); + } + + public DateTimeView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onAttachedToWindow() { + super.onDetachedFromWindow(); + registerReceivers(); + mAttachedToWindow = true; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + unregisterReceivers(); + mAttachedToWindow = false; + } + + @android.view.RemotableViewMethod + public void setTime(long time) { + Time t = new Time(); + t.set(time); + t.second = 0; + mTimeMillis = t.toMillis(false); + mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0); + update(); + } + + void update() { + if (mTime == null) { + return; + } + + long start = System.nanoTime(); + + int display; + Date time = mTime; + + Time t = new Time(); + t.set(mTimeMillis); + t.second = 0; + + t.hour -= 12; + long twelveHoursBefore = t.toMillis(false); + t.hour += 12; + long twelveHoursAfter = t.toMillis(false); + t.hour = 0; + t.minute = 0; + long midnightBefore = t.toMillis(false); + t.monthDay++; + long midnightAfter = t.toMillis(false); + + long nowMillis = System.currentTimeMillis(); + t.set(nowMillis); + t.second = 0; + nowMillis = t.normalize(false); + + // Choose the display mode + choose_display: { + if ((nowMillis >= midnightBefore && nowMillis < midnightAfter) + || (nowMillis >= twelveHoursBefore && nowMillis < twelveHoursAfter)) { + display = SHOW_TIME; + break choose_display; + } + // Else, show month day and year. + display = SHOW_MONTH_DAY_YEAR; + break choose_display; + } + + // Choose the format + DateFormat format; + if (display == mLastDisplay && mLastFormat != null) { + // use cached format + format = mLastFormat; + } else { + switch (display) { + case SHOW_TIME: + format = getTimeFormat(); + break; + case SHOW_MONTH_DAY_YEAR: + format = getDateFormat(); + break; + default: + throw new RuntimeException("unknown display value: " + display); + } + mLastFormat = format; + } + + // Set the text + String text = format.format(mTime); + setText(text); + + // Schedule the next update + if (display == SHOW_TIME) { + // Currently showing the time, update at the later of twelve hours after or midnight. + mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter; + } else { + // Currently showing the date + if (mTimeMillis < nowMillis) { + // If the time is in the past, don't schedule an update + mUpdateTimeMillis = 0; + } else { + // If hte time is in the future, schedule one at the earlier of twelve hours + // before or midnight before. + mUpdateTimeMillis = twelveHoursBefore < midnightBefore + ? twelveHoursBefore : midnightBefore; + } + } + if (false) { + Log.d(TAG, "update needed for '" + time + "' at '" + new Date(mUpdateTimeMillis) + + "' - text=" + text); + } + + long finish = System.nanoTime(); + } + + private DateFormat getTimeFormat() { + int res; + Context context = getContext(); + if (android.text.format.DateFormat.is24HourFormat(context)) { + res = R.string.twenty_four_hour_time_format; + } else { + res = R.string.twelve_hour_time_format; + } + String format = context.getString(res); + return new SimpleDateFormat(format); + } + + private DateFormat getDateFormat() { + String format = Settings.System.getString(getContext().getContentResolver(), + Settings.System.DATE_FORMAT); + if ("".equals(format)) { + return DateFormat.getDateInstance(DateFormat.SHORT); + } else { + return new SimpleDateFormat(format); + } + } + + private void registerReceivers() { + Context context = getContext(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_TIME_TICK); + filter.addAction(Intent.ACTION_TIME_CHANGED); + filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); + context.registerReceiver(mBroadcastReceiver, filter); + + Uri uri = Settings.System.getUriFor(Settings.System.DATE_FORMAT); + context.getContentResolver().registerContentObserver(uri, true, mContentObserver); + } + + private void unregisterReceivers() { + Context context = getContext(); + context.unregisterReceiver(mBroadcastReceiver); + context.getContentResolver().unregisterContentObserver(mContentObserver); + } + + private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_TIME_TICK.equals(action)) { + if (System.currentTimeMillis() < mUpdateTimeMillis) { + // The update() function takes a few milliseconds to run because of + // all of the time conversions it needs to do, so we can't do that + // every minute. + return; + } + } + // ACTION_TIME_CHANGED can also signal a change of 12/24 hr. format. + mLastFormat = null; + update(); + } + }; + + private ContentObserver mContentObserver = new ContentObserver(new Handler()) { + @Override + public void onChange(boolean selfChange) { + mLastFormat = null; + update(); + } + }; +} |