如何在Android中完美地同步时钟应用程序小部件和系统时钟?

如何在Android中完美地同步时钟应用程序小部件和系统时钟?,android,android-intent,android-widget,android-manifest,android-broadcast,Android,Android Intent,Android Widget,Android Manifest,Android Broadcast,我制作了一个数字时钟小部件,它使用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每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秒才能赶上

有没有办法做到以下几点

步骤1:获取系统时间并显示在小部件上

步骤2:设置第一次更新间隔=60-当前秒值

步骤3:第一次更新后,将后续更新间隔设置为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));
}
拦截广播。本地时区时钟每分钟变化一次,就会发送此广播动作

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类的onReceive方法中捕获操作\u TIME\u TICK broadcast,但文档指出,此广播操作只能由以编程方式注册的BroadcastReceiver截获。不过,这可能值得一试。 并不是说使用BroadcastReceiver比使用AlarmManager更好。在不同的情况下需要不同的方法,既然动作时间滴答广播是由系统发送的,为什么不利用它呢?
这是一个老问题,但在Android Oreo和更高版本上使用带有ACTION_TIME_TICK的BroadcastReceiver将不再有效。API级别17+的更好替代方案是使用RemoteView支持的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"/>

时钟应自动与系统时钟同步

感谢ZygoteInit,Bradcastereceiver比AlarmManager更适合时钟小部件吗?我尝试了这个-它工作了大约10分钟-但随后系统关闭了我的进程,它停止了工作…:-@丹尼特:这在我之前参与的一个应用程序小部件项目中非常适合我。如果你能详细解释你的问题,最好是用另一个问题,我将非常乐意帮助你……:@Y.S.我想我明白了-我做了一个服务来更新启动粘性小部件,以确保它不会被关闭。现在效果很好!:-@SaharPournasseh当您截获动作时间刻度广播时,从onReceive启动服务并更新小部件。它对日历有效吗?或者对于日历,只需使用textview?如果我想将小时和分钟分开,该怎么办?例如,小时的字体较大,分钟的字体较小?对于日历,您需要将set24HourFormat和set12HourFormat设置为所需的日期格式。如果您希望小时和分钟的大小不同,则需要两个textclocks,一个格式为HH,另一个格式为mm,分别用于24小时小时:分钟并设置textsize。