【问题标题】:How to ensure PeriodicWorkRequests are called on device reboot on Android N and upwards如何确保在 Android N 及更高版本上的设备重启时调用 PeriodicWorkRequest
【发布时间】:2019-03-22 18:15:26
【问题描述】:

我最近尝试使用WorkManagerPeriodicWorkRequests 作为在后台定期获取用户位置更新的可靠方法。该库满足了我的要求,这个特殊的细节引起了我的注意:

保证任务执行,即使应用或设备重启

实现并测试后,我尝试重新启动设备并注意到日志消息和应用通知从未出现。

当然,我做了一些研究,偶然发现了这个:PeriodicWorkRequest not working after device reboot in android oreo

所以我尝试使用BOOT_COMPLETED 广播接收器在设备重启时触发 WorkRequest,但它不起作用。我检查了许多关于 SO 的 BOOT_COMPLETED 接收者问题,但没有一个有效,除了这里:Broadcast Receiver Not Working After Device Reboot in Android,但这涉及让用户选择你的应用程序作为 AccessibilityService,这在我看来是 UX 的障碍。

经过一番研究,我发现 WorkManager 在后台使用 BOOT_COMPLETED BroadcastReceiver。到目前为止,我一直在 Android Nougat 和 Oreo 设备上进行测试,因此我在运行 API 16 的三星和运行 API 22 的 HTC 上测试了 BroadcastReceiver。他们也工作了!

这是我如何实现我的PeriodicWorkRequest

PeriodicWorkRequest request =
                new PeriodicWorkRequest.Builder(LocationListenerWorker.class,
                        12, HOURS)
                        .build();

        mWorkManager.enqueueUniquePeriodicWork(Constants.LOCATION_TASK_ID,
                ExistingPeriodicWorkPolicy.REPLACE, request);

对于如何确保在运行 API 24+ 的设备上重新启动设备时也调用请求的任何帮助,我们将不胜感激

【问题讨论】:

  • 更新:我发现这不是 API 问题,而是与设备制造商有关。 Tecno 和 Infinix 的 HiOS 和 XOS android 版本限制了收听 BOOT_COMPLETED 广播的访问权限,它也影响了 WorkManager。
  • 您找到解决方案了吗?我也想知道。

标签: android broadcastreceiver android-workmanager


【解决方案1】:

假设您已经定义了一个 RebootWorker 类,它扩展了 Worker 并在设备重新启动后执行一些特定的工作。第一种方法:

public class RebootWorker extends Worker {
...............................
}

在那种情况下,在清单中定义了这个工人

<service
    android:name=".RebootWorker"
    android:process=":worker"/> 

这将有助于让 Workmanger 在设备重启后运行您的工作服务。因为由于设备重启,您的应用会从任务管理器中清除。

第二种方法:你也可以使用 BroadcastReceiver 来监听 Boot 完成的动作

public class MyReceiver extends BroadcastReceiver {
    WorkManager mWorkManager;
    PeriodicWorkRequest rebootRequest;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(MainActivity.TAG, "intent.getAction(): "+intent.getAction());

        //Reboot worker
        mWorkManager = WorkManager.getInstance(context);
        rebootRequest = new PeriodicWorkRequest.Builder(RebootWorker.class,
                MainActivity.REPEAT_INTERVAL, MainActivity.TIME).build();

        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
           //do your work and enqueue it 
            mWorkManager.enqueue(rebootRequest);
}
}
}

【讨论】:

  • 为什么你把worker作为服务放在manifest里面?你在哪里读到的?
  • @Philip 在第一种方法中,我将 RebootWorker 作为服务放入清单中,以便在设备重启时再次启动。
  • 一个 Worker 不是一个 Service。因此这个 AndroidManifest 声明是不准确的。
猜你喜欢
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 2014-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多