import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.database.Cursor;
+import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
// Alarm action for midnight (so we can update the date display).
private static final String ACTION_MIDNIGHT = "com.android.deskclock.MIDNIGHT";
- // 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 QUERY_WEATHER_DELAY = 5 * 60 * 1000; // 5 min
-
+ // Interval between forced polls of the weather widget.
+ private final long QUERY_WEATHER_DELAY = 60 * 60 * 1000; // 1 hr
+
+ // Intent to broadcast for dock settings.
+ private static final String DOCK_SETTINGS_ACTION = "com.android.settings.DOCK_SETTINGS";
+
// Delay before engaging the burn-in protection mode (green-on-black).
- private final long SCREEN_SAVER_TIMEOUT = 5* 60 * 1000; // 10 min
+ private final long SCREEN_SAVER_TIMEOUT = 5 * 60 * 1000; // 5 min
// Repositioning delay in screen saver.
private final long SCREEN_SAVER_MOVE_DELAY = 60 * 1000; // 1 min
// 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
+ private final float DIM_BEHIND_AMOUNT_DIMMED = 0.8f; // higher contrast when display dimmed
// Internal message IDs.
private final int QUERY_WEATHER_DATA_MSG = 0x1000;
}
};
+ private final ContentObserver mContentObserver = new ContentObserver(mHandy) {
+ @Override
+ public void onChange(boolean selfChange) {
+ if (DEBUG) Log.d(LOG_TAG, "content observer notified that weather changed");
+ refreshWeather();
+ }
+ };
+
private void moveScreenSaver() {
moveScreenSaverTo(-1,-1);
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);
+ // we expect the result to show up in our content observer
}
private boolean supportsWeather() {
mWeatherIconDrawable = mGenieResources.getDrawable(cur.getInt(
cur.getColumnIndexOrThrow("iconResId")));
-
+ mWeatherCurrentTemperatureString = String.format("%d\u00b0",
+ (cur.getInt(cur.getColumnIndexOrThrow("temperature"))));
+ mWeatherHighTemperatureString = String.format("%d\u00b0",
+ (cur.getInt(cur.getColumnIndexOrThrow("highTemperature"))));
+ mWeatherLowTemperatureString = String.format("%d\u00b0",
+ (cur.getInt(cur.getColumnIndexOrThrow("lowTemperature"))));
mWeatherLocationString = cur.getString(
cur.getColumnIndexOrThrow("location"));
-
- // any of these may be NULL
- final int colTemp = cur.getColumnIndexOrThrow("temperature");
- final int colHigh = cur.getColumnIndexOrThrow("highTemperature");
- final int colLow = cur.getColumnIndexOrThrow("lowTemperature");
-
- mWeatherCurrentTemperatureString =
- cur.isNull(colTemp)
- ? "\u2014"
- : String.format("%d\u00b0", cur.getInt(colTemp));
- mWeatherHighTemperatureString =
- cur.isNull(colHigh)
- ? "\u2014"
- : String.format("%d\u00b0", cur.getInt(colHigh));
- mWeatherLowTemperatureString =
- cur.isNull(colLow)
- ? "\u2014"
- : String.format("%d\u00b0", cur.getInt(colLow));
} else {
Log.w(LOG_TAG, "No weather information available (cur="
+ cur +")");
mWeatherIconDrawable = null;
+ mWeatherHighTemperatureString = "";
+ mWeatherLowTemperatureString = "";
mWeatherLocationString = getString(R.string.weather_fetch_failure);
- mWeatherCurrentTemperatureString =
- mWeatherHighTemperatureString =
- mWeatherLowTemperatureString = "";
}
mHandy.sendEmptyMessage(UPDATE_WEATHER_DISPLAY_MSG);
if (mDimmed) {
winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
winParams.dimAmount = DIM_BEHIND_AMOUNT_DIMMED;
+ winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF;
// show the window tint
tintView.startAnimation(AnimationUtils.loadAnimation(this,
} else {
winParams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
winParams.dimAmount = DIM_BEHIND_AMOUNT_NORMAL;
+ winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE;
// hide the window tint
tintView.startAnimation(AnimationUtils.loadAnimation(this,
// reload the date format in case the user has changed settings
// recently
- mDateFormat = getString(com.android.internal.R.string.full_wday_month_day_no_year);
+ mDateFormat = getString(R.string.full_wday_month_day_no_year);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_DATE_CHANGED);
filter.addAction(ACTION_MIDNIGHT);
registerReceiver(mIntentReceiver, filter);
+ // Listen for updates to weather data
+ Uri weatherNotificationUri = new Uri.Builder()
+ .scheme(android.content.ContentResolver.SCHEME_CONTENT)
+ .authority(WEATHER_CONTENT_AUTHORITY)
+ .path(WEATHER_CONTENT_PATH)
+ .build();
+ getContentResolver().registerContentObserver(
+ weatherNotificationUri, true, mContentObserver);
+
+ // Elaborate mechanism to find out when the day rolls over
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
+ alarmTimeUTC + " repeating every "
+ AlarmManager.INTERVAL_DAY + " with intent: " + mMidnightIntent);
- // un-dim when resuming
- mDimmed = false;
+ // If we weren't previously visible but now we are, it's because we're
+ // being started from another activity. So it's OK to un-dim.
+ if (mTime != null && mTime.getWindowVisibility() != View.VISIBLE) {
+ mDimmed = false;
+ }
+
+ // Adjust the display to reflect the currently chosen dim mode.
doDim(false);
restoreScreen(); // disable screen saver
// Other things we don't want to be doing in the background.
unregisterReceiver(mIntentReceiver);
+ getContentResolver().unregisterContentObserver(mContentObserver);
+
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.cancel(mMidnightIntent);
unscheduleWeatherQuery();
super.onPause();
}
- @Override
- public void onStop() {
- if (DEBUG) Log.d(LOG_TAG, "onStop");
-
- // Avoid situations where the user launches Alarm Clock and is
- // surprised to find it in dim mode (because it was last used in dim
- // mode, but that last use is long in the past).
- mDimmed = false;
-
- super.onStop();
- }
-
private void initViews() {
// give up any internal focus before we switch layouts
final View focused = getCurrentFocus();
}
}
});
+
+ final View tintView = findViewById(R.id.window_tint);
+ tintView.setOnTouchListener(new View.OnTouchListener() {
+ public boolean onTouch(View v, MotionEvent event) {
+ if (mDimmed && event.getAction() == MotionEvent.ACTION_DOWN) {
+ // We want to un-dim the whole screen on tap.
+ // ...Unless the user is specifically tapping on the dim
+ // widget, in which case let it do the work.
+ Rect r = new Rect();
+ nightmodeButton.getHitRect(r);
+ int[] gloc = new int[2];
+ nightmodeButton.getLocationInWindow(gloc);
+ r.offsetTo(gloc[0], gloc[1]); // convert to window coords
+
+ if (!r.contains((int) event.getX(), (int) event.getY())) {
+ mDimmed = false;
+ doDim(true);
+ }
+ }
+ return false; // always pass the click through
+ }
+ });
+
+ // Tidy up awkward focus behavior: the first view to be focused in
+ // trackball mode should be the alarms button
+ final ViewTreeObserver vto = alarmButton.getViewTreeObserver();
+ vto.addOnGlobalFocusChangeListener(new ViewTreeObserver.OnGlobalFocusChangeListener() {
+ public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+ if (oldFocus == null && newFocus == nightmodeButton) {
+ alarmButton.requestFocus();
+ }
+ }
+ });
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- if (!mScreenSaverMode) {
+ if (mScreenSaverMode) {
+ moveScreenSaver();
+ } else {
initViews();
doDim(false);
refreshAll();
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == R.id.menu_item_alarms) {
- startActivity(new Intent(DeskClock.this, AlarmClock.class));
- return true;
- } else if (item.getItemId() == R.id.menu_item_add_alarm) {
- AlarmClock.addNewAlarm(this);
- return true;
+ switch (item.getItemId()) {
+ case R.id.menu_item_alarms:
+ startActivity(new Intent(DeskClock.this, AlarmClock.class));
+ return true;
+ case R.id.menu_item_add_alarm:
+ AlarmClock.addNewAlarm(this);
+ return true;
+ case R.id.menu_item_dock_settings:
+ startActivity(new Intent(DOCK_SETTINGS_ACTION));
+ return true;
+ default:
+ return false;
}
- return false;
}
@Override