From b95b7a63c403a17c3725e1ccfbd65b4283fd6a0f Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Wed, 18 Nov 2009 14:21:01 -0500 Subject: [PATCH] Myriad fixes & cleanups in DeskClock. - Force the weather widget to actually fetch new data at the moment the device is docked, or when the screensaver disappears (if the device is plugged in). - Use Intent.FLAG_ACTIVITY_CLEAR_TOP to launch weather, music, and gallery to avoid jumping into the middle of their task stacks (http://b/2267831) - Fix layout issues with weather, particularly when the Genie widget is unavailable. (relates to http://b/2254472) - Internationalize the error message shown when Genie malfunctions. - Clean up weather & time displays to match UX specs more closely (fonts, shadow crop issues). - Remove some tabs in XML. - Internal cleanup: use "query" in the name of functions & variables related to getting updated weather from Genie; use "fetch" to refer to downloading new weather data from the network --- res/layout-land/desk_clock.xml | 11 ++-- res/layout/desk_clock_time_date.xml | 12 ++-- res/layout/desk_clock_weather.xml | 18 +++--- res/values/strings.xml | 5 ++ src/com/android/deskclock/DeskClock.java | 96 +++++++++++++++++++------------- 5 files changed, 85 insertions(+), 57 deletions(-) diff --git a/res/layout-land/desk_clock.xml b/res/layout-land/desk_clock.xml index 6ea363b..c956195 100644 --- a/res/layout-land/desk_clock.xml +++ b/res/layout-land/desk_clock.xml @@ -55,7 +55,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:gravity="left" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceMedium" android:drawablePadding="6dip" android:drawableLeft="@drawable/ic_lock_idle_alarm" android:shadowColor="#C0000000" @@ -72,7 +72,7 @@ /> diff --git a/res/layout/desk_clock_time_date.xml b/res/layout/desk_clock_time_date.xml index 411115e..2c14595 100644 --- a/res/layout/desk_clock_time_date.xml +++ b/res/layout/desk_clock_time_date.xml @@ -27,12 +27,14 @@ @@ -47,9 +50,10 @@ android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="bottom" - android:textAppearance="?android:attr/textAppearanceMedium" - android:textStyle="bold" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textStyle="bold" android:singleLine="true" + android:ellipsize="none" android:layout_marginLeft="3dip" android:shadowColor="#C0000000" android:shadowDx="0" @@ -63,7 +67,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="left" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceMedium" android:shadowColor="#C0000000" android:shadowDx="0" android:shadowDy="0" diff --git a/res/layout/desk_clock_weather.xml b/res/layout/desk_clock_weather.xml index c5ee761..6c17162 100644 --- a/res/layout/desk_clock_weather.xml +++ b/res/layout/desk_clock_weather.xml @@ -18,9 +18,8 @@ @@ -83,8 +83,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/weather_temp_icon_cluster" + android:maxWidth="300sp" android:gravity="left" - android:singleLine="true" android:textSize="18sp" android:textColor="#ffffffff" android:shadowColor="#c0000000" diff --git a/res/values/strings.xml b/res/values/strings.xml index d14b740..574b45c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -235,6 +235,11 @@ %d%% + + + Weather information currently unavailable. diff --git a/src/com/android/deskclock/DeskClock.java b/src/com/android/deskclock/DeskClock.java index 654d6d9..0cd65a5 100644 --- a/src/com/android/deskclock/DeskClock.java +++ b/src/com/android/deskclock/DeskClock.java @@ -97,7 +97,7 @@ public class DeskClock extends Activity { // Interval between polls of the weather widget. Its refresh period is // likely to be much longer (~3h), but we want to pick up any changes // within 5 minutes. - private final long FETCH_WEATHER_DELAY = 5 * 60 * 1000; // 5 min + private final long QUERY_WEATHER_DELAY = 5 * 60 * 1000; // 5 min // Delay before engaging the burn-in protection mode (green-on-black). private final long SCREEN_SAVER_TIMEOUT = 10 * 60 * 1000; // 10 min @@ -109,8 +109,12 @@ public class DeskClock extends Activity { private final int SCREEN_SAVER_COLOR = 0xFF308030; private final int SCREEN_SAVER_COLOR_DIM = 0xFF183018; + // Opacity of black layer between clock display and wallpaper. + private final float DIM_BEHIND_AMOUNT_NORMAL = 0.4f; + private final float DIM_BEHIND_AMOUNT_DIMMED = 0.7f; // higher contrast when display dimmed + // Internal message IDs. - private final int FETCH_WEATHER_DATA_MSG = 0x1000; + private final int QUERY_WEATHER_DATA_MSG = 0x1000; private final int UPDATE_WEATHER_DISPLAY_MSG = 0x1001; private final int SCREEN_SAVER_TIMEOUT_MSG = 0x2000; private final int SCREEN_SAVER_MOVE_MSG = 0x2001; @@ -130,6 +134,8 @@ public class DeskClock extends Activity { "description", }; + private static final String ACTION_GENIE_REFRESH = "com.google.android.apps.genie.REFRESH"; + // State variables follow. private DigitalClock mTime; private TextView mDate; @@ -163,8 +169,6 @@ public class DeskClock extends Activity { private int mIdleTimeoutEpoch = 0; - private boolean mWeatherFetchScheduled = false; - private Random mRNG; private PendingIntent mMidnightIntent; @@ -186,11 +190,9 @@ public class DeskClock extends Activity { private final Handler mHandy = new Handler() { @Override public void handleMessage(Message m) { - if (m.what == FETCH_WEATHER_DATA_MSG) { - if (!mWeatherFetchScheduled) return; - mWeatherFetchScheduled = false; - new Thread() { public void run() { fetchWeatherData(); } }.start(); - scheduleWeatherFetchDelayed(FETCH_WEATHER_DELAY); + if (m.what == QUERY_WEATHER_DATA_MSG) { + new Thread() { public void run() { queryWeatherData(); } }.start(); + scheduleWeatherQueryDelayed(QUERY_WEATHER_DELAY); } else if (m.what == UPDATE_WEATHER_DISPLAY_MSG) { updateWeatherDisplay(); } else if (m.what == SCREEN_SAVER_TIMEOUT_MSG) { @@ -257,6 +259,8 @@ public class DeskClock extends Activity { mScreenSaverMode = false; initViews(); doDim(false); // restores previous dim mode + // policy: update weather info when returning from screen saver + if (mPluggedIn) requestWeatherDataFetch(); refreshAll(); } @@ -293,8 +297,8 @@ public class DeskClock extends Activity { mDate.setTextColor(color); mNextAlarm.setTextColor(color); mNextAlarm.setCompoundDrawablesWithIntrinsicBounds( - getResources().getDrawable(mDimmed - ? R.drawable.ic_lock_idle_alarm_saver_dim + getResources().getDrawable(mDimmed + ? R.drawable.ic_lock_idle_alarm_saver_dim : R.drawable.ic_lock_idle_alarm_saver), null, null, null); @@ -317,25 +321,32 @@ public class DeskClock extends Activity { restoreScreen(); } + // Tell the Genie widget to load new data from the network. + private void requestWeatherDataFetch() { + if (DEBUG) Log.d(LOG_TAG, "forcing the Genie widget to update weather now..."); + sendBroadcast(new Intent(ACTION_GENIE_REFRESH).putExtra("requestWeather", true)); + // update the display with any new data + scheduleWeatherQueryDelayed(5000); + } + private boolean supportsWeather() { return (mGenieResources != null); } - private void scheduleWeatherFetchDelayed(long delay) { - if (mWeatherFetchScheduled) return; + private void scheduleWeatherQueryDelayed(long delay) { + // cancel any existing scheduled queries + unscheduleWeatherQuery(); if (DEBUG) Log.d(LOG_TAG, "scheduling weather fetch message for " + delay + "ms from now"); - mWeatherFetchScheduled = true; - - mHandy.sendEmptyMessageDelayed(FETCH_WEATHER_DATA_MSG, delay); + mHandy.sendEmptyMessageDelayed(QUERY_WEATHER_DATA_MSG, delay); } - private void unscheduleWeatherFetch() { - mWeatherFetchScheduled = false; + private void unscheduleWeatherQuery() { + mHandy.removeMessages(QUERY_WEATHER_DATA_MSG); } - private void fetchWeatherData() { + private void queryWeatherData() { // if we couldn't load the weather widget's resources, we simply // assume it's not present on the device. if (mGenieResources == null) return; @@ -392,7 +403,7 @@ public class DeskClock extends Activity { mWeatherIconDrawable = null; mWeatherHighTemperatureString = ""; mWeatherLowTemperatureString = ""; - mWeatherLocationString = "Weather data unavailable."; // TODO: internationalize + mWeatherLocationString = getString(R.string.weather_fetch_failure); } mHandy.sendEmptyMessage(UPDATE_WEATHER_DISPLAY_MSG); @@ -400,7 +411,7 @@ public class DeskClock extends Activity { private void refreshWeather() { if (supportsWeather()) - scheduleWeatherFetchDelayed(0); + scheduleWeatherQueryDelayed(0); updateWeatherDisplay(); // in case we have it cached } @@ -419,6 +430,11 @@ public class DeskClock extends Activity { final boolean pluggedIn = (plugStatus == BATTERY_STATUS_CHARGING || plugStatus == BATTERY_STATUS_FULL); if (pluggedIn != mPluggedIn) { setWakeLock(pluggedIn); + + if (pluggedIn) { + // policy: update weather info when attaching to power + requestWeatherDataFetch(); + } } if (pluggedIn != mPluggedIn || batteryLevel != mBatteryLevel) { mBatteryLevel = batteryLevel; @@ -484,7 +500,7 @@ public class DeskClock extends Activity { if (mDimmed) { winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; - winParams.dimAmount = 0.67f; // pump up contrast in dim mode + winParams.dimAmount = DIM_BEHIND_AMOUNT_DIMMED; // show the window tint tintView.startAnimation(AnimationUtils.loadAnimation(this, @@ -492,7 +508,7 @@ public class DeskClock extends Activity { : R.anim.dim_instant)); } else { winParams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN); - winParams.dimAmount = 0.5f; // lower contrast in normal mode + winParams.dimAmount = DIM_BEHIND_AMOUNT_NORMAL; // hide the window tint tintView.startAnimation(AnimationUtils.loadAnimation(this, @@ -524,8 +540,8 @@ public class DeskClock extends Activity { am.setRepeating(AlarmManager.RTC, today.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mMidnightIntent); registerReceiver(mIntentReceiver, filter); - doDim(false); - restoreScreen(); + doDim(false); // un-dim when resuming + restoreScreen(); // disable screen saver refreshAll(); // will schedule periodic weather fetch setWakeLock(mPluggedIn); @@ -535,14 +551,13 @@ public class DeskClock extends Activity { Message.obtain(mHandy, SCREEN_SAVER_TIMEOUT_MSG, mIdleTimeoutEpoch, 0), SCREEN_SAVER_TIMEOUT); - final boolean launchedFromDock + final boolean launchedFromDock = getIntent().hasCategory(Intent.CATEGORY_DESK_DOCK); if (supportsWeather() && launchedFromDock && !mInDock) { + // policy: fetch weather if launched via dock connection if (DEBUG) Log.d(LOG_TAG, "Device now docked; forcing weather to refresh right now"); - sendBroadcast( - new Intent("com.google.android.apps.genie.REFRESH") - .putExtra("requestWeather", true)); + requestWeatherDataFetch(); } mInDock = launchedFromDock; @@ -559,7 +574,7 @@ public class DeskClock extends Activity { unregisterReceiver(mIntentReceiver); AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE); am.cancel(mMidnightIntent); - unscheduleWeatherFetch(); + unscheduleWeatherQuery(); super.onPause(); } @@ -595,14 +610,17 @@ public class DeskClock extends Activity { mWeatherLocation = (TextView) findViewById(R.id.weather_location); mWeatherIcon = (ImageView) findViewById(R.id.weather_icon); - mNextAlarm = (TextView) findViewById(R.id.nextAlarm); - - final ImageButton alarmButton = (ImageButton) findViewById(R.id.alarm_button); - alarmButton.setOnClickListener(new View.OnClickListener() { + final View.OnClickListener alarmClickListener = new View.OnClickListener() { public void onClick(View v) { startActivity(new Intent(DeskClock.this, AlarmClock.class)); } - }); + }; + + mNextAlarm = (TextView) findViewById(R.id.nextAlarm); + mNextAlarm.setOnClickListener(alarmClickListener); + + final ImageButton alarmButton = (ImageButton) findViewById(R.id.alarm_button); + alarmButton.setOnClickListener(alarmClickListener); final ImageButton galleryButton = (ImageButton) findViewById(R.id.gallery_button); galleryButton.setOnClickListener(new View.OnClickListener() { @@ -612,7 +630,7 @@ public class DeskClock extends Activity { Intent.ACTION_VIEW, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI) .putExtra("slideshow", true) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP)); } catch (android.content.ActivityNotFoundException e) { Log.e(LOG_TAG, "Couldn't launch image browser", e); } @@ -625,7 +643,7 @@ public class DeskClock extends Activity { try { Intent musicAppQuery = getPackageManager() .getLaunchIntentForPackage(MUSIC_PACKAGE_ID) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP); if (musicAppQuery != null) { startActivity(musicAppQuery); } @@ -640,7 +658,7 @@ public class DeskClock extends Activity { public void onClick(View v) { startActivity( new Intent(Intent.ACTION_MAIN) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP) .addCategory(Intent.CATEGORY_HOME)); } }); @@ -667,7 +685,7 @@ public class DeskClock extends Activity { Intent genieAppQuery = getPackageManager() .getLaunchIntentForPackage(GENIE_PACKAGE_ID) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP); if (genieAppQuery != null) { startActivity(genieAppQuery); } -- 2.11.0