OSDN Git Service

Myriad fixes & cleanups in DeskClock.
authorDaniel Sandler <dsandler@google.com>
Wed, 18 Nov 2009 19:21:01 +0000 (14:21 -0500)
committerDaniel Sandler <dsandler@google.com>
Wed, 18 Nov 2009 20:18:43 +0000 (15:18 -0500)
 - 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
res/layout/desk_clock_time_date.xml
res/layout/desk_clock_weather.xml
res/values/strings.xml
src/com/android/deskclock/DeskClock.java

index 6ea363b..c956195 100644 (file)
@@ -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 @@
                     />
 
                 <ImageButton android:id="@+id/nightmode_button"
-                                       style="@style/RoundTouchButton"
+                    style="@style/RoundTouchButton"
                     android:layout_weight="0"
                     android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
 
                 <include layout="@layout/desk_clock_time_date"
                     android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
-                    android:layout_weight="1"
+                    android:layout_width="0dip"
+                    android:layout_weight="4"
                     />
 
                 <include layout="@layout/desk_clock_weather"
                     android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"
+                    android:layout_width="0dip"
                     android:layout_marginLeft="12dip"
+                    android:layout_weight="3"
                     />
 
 
index 411115e..2c14595 100644 (file)
     <com.android.deskclock.DigitalClock android:id="@+id/time"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="12dip"
+        android:layout_marginBottom="8dip"
         >
 
         <TextView android:id="@+id/timeDisplay"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:ellipsize="none"
             android:gravity="center"
             android:textSize="106sp"
             android:textColor="#FFFFFFFF"
@@ -40,6 +42,7 @@
             android:shadowDx="0"
             android:shadowDy="0"
             android:shadowRadius="3.0"
+            android:paddingBottom="3dip"
             />
 
 
             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"
index c5ee761..6c17162 100644 (file)
@@ -18,9 +18,8 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/weather"
     android:orientation="vertical"
-    android:layout_width="fill_parent"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_weight="0"
     android:gravity="left"
     >
     <RelativeLayout android:id="@+id/weather_temp_icon_cluster"
@@ -41,7 +40,7 @@
             android:layout_height="wrap_content"
             android:singleLine="true"
             android:textSize="46sp"
-                       android:textColor="?android:attr/textColorPrimary"
+            android:textColor="?android:attr/textColorPrimary"
             android:shadowColor="#C0000000"
             android:shadowDx="0"
             android:shadowDy="0"
@@ -55,8 +54,8 @@
             android:layout_width="40sp"
             android:layout_height="wrap_content"
             android:singleLine="true"
-                       android:textAppearance="?android:attr/textAppearanceSmall"
-                       android:textColor="?android:attr/textColorSecondary"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textColor="?android:attr/textColorSecondary"
             android:shadowColor="#C0000000"
             android:shadowDx="0"
             android:shadowDy="0"
             android:layout_width="40sp"
             android:layout_height="wrap_content"
             android:singleLine="true"
-                       android:textAppearance="?android:attr/textAppearanceSmall"
-                       android:textColor="?android:attr/textColorPrimary"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textStyle="bold"
+            android:textColor="?android:attr/textColorPrimary"
             android:shadowColor="#C0000000"
             android:shadowDx="0"
             android:shadowDy="0"
             android:shadowRadius="3.0"
             android:layout_alignTop="@id/weather_temperature"
-            android:layout_marginTop="4sp"
+            android:layout_marginTop="9sp"
             android:layout_alignLeft="@id/weather_low_temperature"
             />
     </RelativeLayout>
@@ -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"
index d14b740..574b45c 100644 (file)
 
     <!-- A short representation of charging information, e.g "34%" -->
     <string name="battery_charging_level"><xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string>
+
+    <!-- What to show the user if the weather widget exists but fails to
+         respond. This is a sign of an error; if the weather widget is not
+         present on the device, we show nothing at all. -->
+    <string name="weather_fetch_failure">Weather information currently unavailable.</string>
 </resources>
 
 
index 654d6d9..0cd65a5 100644 (file)
@@ -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);
                 }