假设我有一个应用程序的小部件,它的targetSDKVersion设置为26。这个小部件需要100到10毫秒的时间来更新。大多数情况下低于1秒。在Android之前,如果在我的AppWidgetProvider上调用了onUpdate(),我可以启动一个后台服务来更新这个小部件。但是,如果尝试这种行为,Android会返回一个IllegalStateException。启动前台服务的显而易见的解决方案似乎是一个极端的措施,它将在10s以下的99%时间内完成。
可能的解决办法
我个人不喜欢上述任何一种解决方案。希望我错过了什么。
(更令人沮丧的是,我的应用程序已经通过调用onUpdate()的系统加载到内存中。我不知道如何将我的应用程序加载到内存中来调用onUpdate(),但如果不给我的app 1在UI线程上更新小部件,就可以节省任何人的电池寿命。)
发布于 2017-09-12 16:06:19
您没有指示更新触发机制是什么。您似乎关心延迟(“您的小部件可能会或不会在一段时间内得到更新”),因此我将假设您的关注与用户与应用程序小部件的交互有关,例如点击按钮。
使用JobScheduler尽可能快地安排作业。您的小部件可能会更新一段时间,也可能不会更新。
这是"use JobIntentService“的一个变体,AFAIK是这种场景的推荐解决方案。
其他选择包括:
getForegroundService()与PendingIntent结合使用。这样,您就可以有效地“轻信”您的服务将在ANR时间范围内调用startForeground()。如果工作时间超过几秒钟,打电话给startForeground(),确保安卓不会变得疯狂。这应尽量减少前台通知出现的时间。而且,如果用户单击一个按钮,而您几秒钟后仍忙于工作,您可能希望显示一个通知或以其他方式让用户知道他们要求的内容仍在进行中。goAsync() on BroadcastReceiver,可以在接收方的上下文中完成工作,同时不绑定主应用程序线程。我还没有在安卓8.0+上试过这个,所以YMMV。发布于 2020-02-18 07:01:15
您可以使用WorkManager更新一个小部件。在带有API 14+的设备上使用WorkManager。您需要覆盖有趣的onReceive(上下文:上下文?,意图:意图?)就像这样:
val ACTION_AUTO_UPDATE : String = "AUTO_UPDATE";
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
if(intent?.action.equals(ACTION_AUTO_UPDATE))
{
val appWidgetManager = AppWidgetManager.getInstance(context)
val thisAppWidgetComponentName = ComponentName(context!!.getPackageName(), javaClass.name)
val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName)
for (appWidgetId in appWidgetIds) {
// update widget
}
}
}您应该创建PeriodicWorkRequest。你必须用来重复工作。定期工作至少间隔15分钟。当小部件启用时,我们对periodicWork进行排队:
override fun onEnabled(context: Context) {
val periodicWorkRequest = PeriodicWorkRequest.Builder(YourWorker::class.java, 15, TimeUnit.MINUTES).build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork("YourWorker", ExistingPeriodicWorkPolicy.REPLACE,periodicWorkRequest)
}并在禁用小部件时取消它:
override fun onDisabled(context: Context) {
WorkManager.getInstance(context).cancelAllWork()
}最后,我们创建了worker类:
class YourWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) {
var context : Context? = null
init {
context = ctx
}
override fun doWork(): Result {
val alarmIntent = Intent(context, YourWidget::class.java)
alarmIntent.action = YourWidget().ACTION_AUTO_UPDATE
context?.sendBroadcast(alarmIntent)
return Result.success()
}如果要使用WorkerManager,则向build.gradle实现中添加‘androidx.work:work:2.3.1’
您可以找到样本这里。
https://stackoverflow.com/questions/46179256
复制相似问题