如何在 Android 中完美同步时钟应用程序小部件与系统时钟?
How to perfectly sync clock app widget with system clock in Android?
我制作了一个数字时钟小部件,它使用 AlarmManager
每 60 秒更新一次时间。
@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));
}
问题是,每 60 秒轮询一次系统时间不会使我的小部件时间与系统时间同步。假设用户在 6:00:20 添加小部件,我的小部件显示时间 6:00 并休眠 60 秒,因此当系统时间变为 6:01:00 时,我的小部件需要另外 20 秒才能赶上。
有没有办法做到以下几点?
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.
拦截 ACTION_TIME_TICK
广播。此广播操作在本地时区时钟每分钟更改时发送一次。
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);
}
进一步考虑:
- 我们可以尝试在
AppWidgetProvider
class' onReceive()
方法中捕获 ACTION_TIME_TICK
广播(在将操作添加到 intent-filter
之后清单),但文档指出此广播操作只能被以编程方式注册的 BroadcastReceiver
拦截。不过,这可能值得一试。
- 并不是说使用
BroadcastReceiver
比使用 AlarmManager
更 "better"。不同的情况需要不同的方法,既然ACTION_TIME_TICK
广播是由系统发送的,为什么不利用它呢?
这是一个老问题,但是在 Android Oreo 及更高版本上将 BroadcastReceiver 与 ACTION_TIME_TICK
一起使用将不再有效。 API 级别 17+ 的更好替代方法是使用 RemoteViews
支持的 TextClock
。只需在您的时钟小部件布局中添加如下内容:
<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"/>
时钟应自动与系统时钟同步。
我制作了一个数字时钟小部件,它使用 AlarmManager
每 60 秒更新一次时间。
@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));
}
问题是,每 60 秒轮询一次系统时间不会使我的小部件时间与系统时间同步。假设用户在 6:00:20 添加小部件,我的小部件显示时间 6:00 并休眠 60 秒,因此当系统时间变为 6:01:00 时,我的小部件需要另外 20 秒才能赶上。
有没有办法做到以下几点?
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.
拦截 ACTION_TIME_TICK
广播。此广播操作在本地时区时钟每分钟更改时发送一次。
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);
}
进一步考虑:
- 我们可以尝试在
AppWidgetProvider
class'onReceive()
方法中捕获ACTION_TIME_TICK
广播(在将操作添加到intent-filter
之后清单),但文档指出此广播操作只能被以编程方式注册的BroadcastReceiver
拦截。不过,这可能值得一试。 - 并不是说使用
BroadcastReceiver
比使用AlarmManager
更 "better"。不同的情况需要不同的方法,既然ACTION_TIME_TICK
广播是由系统发送的,为什么不利用它呢?
这是一个老问题,但是在 Android Oreo 及更高版本上将 BroadcastReceiver 与 ACTION_TIME_TICK
一起使用将不再有效。 API 级别 17+ 的更好替代方法是使用 RemoteViews
支持的 TextClock
。只需在您的时钟小部件布局中添加如下内容:
<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"/>
时钟应自动与系统时钟同步。