问题
I made a digital clock widget which is using AlarmManager
to update the time every 60 seconds.
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
Log.d("onEnabled","Widget Provider enabled. Starting timer to update widget every minute");
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 60000, createClockTickIntent(context));
}
The problem is, polling the system time every 60 seconds does not sync my widget time with system time. lets say user adds widget at 6:00:20, my widget shows the time 6:00 and sleeps for 60 seconds, so when system time becomes 6:01:00, my widget needs another 20 seconds to catch up.
Is there a way to do the following ?
step 1: get system time and show on widget.
step 2: set the first update interval = (60 - current Seconds value).
step 3: after first update, set the subsequent update intervals to 60 seconds.
回答1:
Intercept the ACTION_TIME_TICK broadcast. This broadcast action is sent on every minute change of the local time zone clock.
private BroadcastReceiver receiver;
@Override
public void onEnabled(Context context)
{
super.onEnabled();
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context ctx, Intent intent)
{
if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0) {
// update widget time here using System.currentTimeMillis()
}
}
};
context.getApplicationContext().registerReceiver(receiver, new IntentFilter(Intent.ACTION_TIME_TICK));
}
@Override
public void onDisabled(Context context)
{
super.onDisabled();
if (receiver != null)
context.getApplicationContext().unregisterReceiver(receiver);
}
Further considerations:
- We could have tried catching the
ACTION_TIME_TICK
broadcast in theAppWidgetProvider
class'onReceive()
method (after adding the action to theintent-filter
in the manifest) but the documentation states that this broadcast action can only be intercepted by aBroadcastReceiver
registered programmatically. Still, this may be worth a try. - It is not that using a
BroadcastReceiver
is "better" than using theAlarmManager
. Different approaches are required in different situations, and since theACTION_TIME_TICK
broadcast is sent by the system, why not exploit that ?
回答2:
This is an old question but using BroadcastReceiver with ACTION_TIME_TICK
on Android Oreo and above won't work anymore. An better alternative for API Level 17+ would be to use TextClock
which is supported by RemoteViews
. Just add something like this in your clock widget layout:
<TextClock
android:id="@+id/widget_clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="56sp"
tools:text="12:45"
<!-- You can also easily add custom typefaces -->
android:fontFamily="@font/quicksand_regular"
android:textColor="@color/white"/>
The clock should sync automatically with the system clock.
来源:https://stackoverflow.com/questions/29345686/how-to-perfectly-sync-clock-app-widget-with-system-clock-in-android