diff options
author | Joe Onorato <joeo@google.com> | 2010-01-19 16:45:05 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-01-19 16:45:05 -0800 |
commit | fd24feaf796f51866c7354a02d4d8febe255b115 (patch) | |
tree | 3a2c43068db20ec61e5b57a1e61df671938ba057 | |
parent | 290cd9ab8b5f3043e18be665763c914f4d3d7dc5 (diff) | |
parent | c83bb730ec0333e52990a40edf6d54bb66b1d5ba (diff) | |
download | frameworks_base-fd24feaf796f51866c7354a02d4d8febe255b115.zip frameworks_base-fd24feaf796f51866c7354a02d4d8febe255b115.tar.gz frameworks_base-fd24feaf796f51866c7354a02d4d8febe255b115.tar.bz2 |
Merge "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."
4 files changed, 281 insertions, 6 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index be5a7d3..4d72f73 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -443,11 +443,7 @@ public class Notification implements Parcelable contentView.setTextViewText(com.android.internal.R.id.text, contentText); } if (this.when != 0) { - Date date = new Date(when); - CharSequence str = - DateUtils.isToday(when) ? DateFormat.getTimeFormat(context).format(date) - : DateFormat.getDateFormat(context).format(date); - contentView.setTextViewText(com.android.internal.R.id.time, str); + contentView.setLong(com.android.internal.R.id.time, "setTime", when); } this.contentView = contentView; 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(); + } + }; +} diff --git a/core/res/res/layout/status_bar_latest_event_content.xml b/core/res/res/layout/status_bar_latest_event_content.xml index 2f7036f..c3aa041 100644 --- a/core/res/res/layout/status_bar_latest_event_content.xml +++ b/core/res/res/layout/status_bar_latest_event_content.xml @@ -45,7 +45,7 @@ android:textSize="14sp" android:paddingLeft="4dp" /> - <TextView android:id="@+id/time" + <android.widget.DateTimeView android:id="@+id/time" android:layout_marginLeft="4dp" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java index f2ddd0f..ffc2cbc 100644 --- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java +++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java @@ -121,6 +121,20 @@ public class NotificationTestList extends TestActivity } }, + new Test("Times") { + public void run() + { + long now = System.currentTimeMillis(); + + timeNotification(7, "24 hours from now", now+(1000*60*60*24)); + timeNotification(6, "12:01:00 from now", now+(1000*60*60*12)+(60*1000)); + timeNotification(5, "12 hours from now", now+(1000*60*60*12)); + timeNotification(4, "now", now); + timeNotification(3, "11:59:00 ago", now-((1000*60*60*12)-(60*1000))); + timeNotification(2, "12 hours ago", now-(1000*60*60*12)); + timeNotification(1, "24 hours ago", now-(1000*60*60*24)); + } + }, new StateStress("Stress - Ongoing / Latest", 100, 100, new Runnable[] { new Runnable() { public void run() { @@ -590,5 +604,12 @@ public class NotificationTestList extends TestActivity mHandler.postDelayed(mRunnable, mPause); } } + + void timeNotification(int n, String label, long time) { + mNM.notify(n, new Notification(NotificationTestList.this, + R.drawable.ic_statusbar_missedcall, null, + time, label, "" + new java.util.Date(time), null)); + + } } |