如何像KWGT(Kustom Widget)一样每分钟更新一次时间widget?

How to update time widget every minute like KWGT(Kustom Widget)?

更新

我放弃了使用ACTION_TIME_TICK,因为当点击锁定的phone的物理按钮时,即使phone仍然处于锁定状态,它也会发送ACTION_TIME_TICK。一直按着唤醒phone.

可能会出问题

编辑

本题的初衷: 每 60 秒更新一次小部件文本(不是 TextClock)? 我可以使用 ACTION_TIME_TICK 来更新 android 时间小部件吗?

我发现一个名为 KWGT(Kustom Widget) and seems like using background?foreground service 的应用程序每分钟更新一次。它的服务(显示通知,所以我确定它是服务)比我的(警报+前台服务)寿命更长。

KWGT 如何做到这一点?它的帮助网站说:Kustom was using close to 0 resources when it was allowed to ignore battery optimization (because targeting old releases) and new version acts like the same.是否意味着使用AlarmManager.RTC模式的警报?

我有一个显示 HH:mm 的 Android AppWidget,每 60 秒更新一次,它可以工作,但仍然存在一些问题。这是我得到的:

  1. 我试过TextClock,好像不错,但我还需要在时间流逝时更新一些其他文本,比如“倒计时:3分钟”、“倒计时:2分钟”。

  2. 我使用 AlarmManager,每分钟发送一次广播来更新我的小部件。我有点担心我设备的电池。另一个问题是,当我更改设备的时间时,TextClock 会立即获得新时间,但我的小部件文本不会。

  3. 我知道TextClock是怎么做的:系统发送的意图ACTION_TIME_TICK、ACTION_TIME_CHANGED、ACTION_TIMEZONE_CHANGED。注释说:“您不能通过清单中声明的​​组件接收它,只能通过使用 Context.registerReceiver() 明确注册它”。

  4. 那么,我应该在服务中注册那个接收器吗?我认为它不会工作很长时间,因为我的进程不能永远 运行。那些系统时间小部件如何做到这一点? 2021 年最好的方式是什么?我的minSdk是API26,如果以后有更好的办法,我可以换到更高的版本。

我的闹钟:

fun startAlarm() {
        val calendar: Calendar = Calendar.getInstance()
        calendar.set(Calendar.MILLISECOND, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.add(Calendar.MINUTE, 1)
        val alarmIntent = Intent(context, MyWidget::class.java)
        alarmIntent.action = MyWidget.ACTION_AUTO_UPDATE
        val pendingIntent = PendingIntent.getBroadcast(
            context,
            ALARM_ID,
            alarmIntent,
            PendingIntent.FLAG_CANCEL_CURRENT
        )
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        // RTC does not wake the device up
        alarmManager.setRepeating(
            AlarmManager.RTC,
            calendar.timeInMillis,
            INTERVAL_MILLIS.toLong(), // Value will be forced up to 60000 as of Android 5.1
            pendingIntent
        )
    }

有趣的 registerReceiver 说:

注意:不能从 BroadcastReceiver 组件调用此方法;也就是说,来自应用程序清单中声明的​​ BroadcastReceiver。但是,可以从另一个 BroadcastReceiver 调用此方法,该 BroadcastReceiver 本身已在 运行 时使用 registerReceiver 注册,因为此类已注册 BroadcastReceiver 的生命周期与注册它的对象相关

这是什么意思?我可以在 class MyWidget : AppWidgetProvider() 中注册它吗?正确的上下文是什么?

这是 TextClock 中的接收寄存器:

    // OK, this is gross but needed. This class is supported by the
    // remote views mechanism and as a part of that the remote views
    // can be inflated by a context for another user without the app
    // having interact users permission - just for loading resources.
    // For example, when adding widgets from a managed profile to the
    // home screen. Therefore, we register the receiver as the user
    // the app is running as not the one the context is for.
    getContext().registerReceiverAsUser(
        mIntentReceiver,
        android.os.Process.myUserHandle(),
        filter,
        null,
        getHandler()
    );

registerReceiverAsUser是一个带有@UnsupportedAppUsage的函数,所以我认为它帮不了我。

非常感谢。

您可以覆盖从 AppWidgetProvider 扩展的 class 中列出的方法,如下所示:

@Override
public void onReceive(Context context, Intent intent)
{
    super.onReceive(context, intent);        
    Log.d("TAG", "mythou--------->onReceive Reason: " + intent.getAction());
    
}

@Override
public void onEnabled(Context context) {
    // Enter relevant functionality for when the first widget is created
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_TIME_TICK);
    filter.addAction(Intent.ACTION_TIME_CHANGED);
    context.getApplicationContext().registerReceiver(this, filter);
}

最好的方法是尽可能使用 TextClock or AnalogClock。这些更新每分钟(或 Android 12 上的 AnalogClock 的秒),而您的应用程序进程不需要 运行.

ACTION_TIME_TICK 仅发送给已注册的接收者,这意味着当您的应用程序未 运行ning 时您将不会收到它。让您的应用程序保持 运行 唯一可行的方法是使用前台服务,需要向用户显示通知。