Periodic Worker 在 AndroidX 中

huangapple go评论99阅读模式
英文:

Periodic Worker in androidx

问题

androidx.work.Worker 仅在应用程序运行时才能工作。如果应用程序终止,PeriodicWorkRequest 将停止执行周期性启动。

为了在特定时间间隔显示通知,我使用 PeriodicWorkRequest,当应用程序运行时(即使处于最小化状态),它会按预期工作,但如果进程终止,就不会再有通知。

工作类

  1. import androidx.work.ExistingPeriodicWorkPolicy;
  2. import androidx.work.Operation;
  3. import androidx.work.PeriodicWorkRequest;
  4. import androidx.work.WorkManager;
  5. import androidx.work.WorkerParameters;
  6. import java.util.concurrent.TimeUnit;
  7. public class Worker extends androidx.work.Worker {
  8. public static final String NOTIFICATION_TAG = "Notification";
  9. public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
  10. super(context, workerParams);
  11. Log.d(TAG, "NotificationWorkerInit");
  12. }
  13. @NonNull
  14. @Override
  15. public Result doWork() {
  16. Log.d(TAG, "doWork: START");
  17. Notification.showNotification(getApplicationContext());
  18. return Result.success();
  19. }
  20. public static void doNotifications(Context context, int quantityPerDay) {
  21. if (quantityPerDay > 0) {
  22. startNotifications(context, quantityPerDay);
  23. } else {
  24. stopNotifications(context);
  25. }
  26. }
  27. private static void startNotifications(Context context, int interval) {
  28. int minInterval = 1;
  29. PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
  30. .Builder(Worker.class, interval, TimeUnit.SECONDS, minInterval, TimeUnit.SECONDS)
  31. .addTag(NOTIFICATION_TAG)
  32. .build();
  33. Log.d(TAG, "startNotificationsService: tag " + notificationsWorker.getTags());
  34. Log.d(TAG, "startNotificationsService: id " + notificationsWorker.getId());
  35. WorkManager workManager = WorkManager.getInstance(context);
  36. Operation enqueue = workManager.enqueueUniquePeriodicWork(NOTIFICATION_TAG,
  37. ExistingPeriodicWorkPolicy.REPLACE, notificationsWorker);
  38. }
  39. private static void stopNotifications(Context context) {
  40. WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_TAG);
  41. Log.d(TAG, "stopNotifications: ");
  42. }
  43. }

依赖项 build.gradle(应用程序)

  1. dependencies {
  2. implementation fileTree(dir: 'libs', include: ['*.jar'])
  3. implementation 'androidx.appcompat:appcompat:1.2.0'
  4. implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
  5. implementation 'androidx.recyclerview:recyclerview:1.1.0'
  6. implementation 'androidx.work:work-runtime:2.4.0'
  7. implementation 'com.github.judemanutd:autostarter:1.0.8'
  8. testImplementation 'junit:junit:4.13'
  9. androidTestImplementation 'androidx.test.ext:junit:1.1.1'
  10. androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
  11. }

清单权限(无服务,无接收器)

  1. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
  2. <uses-permission android:name="android.permission.INTERNET"/>
  3. <uses-permission android:name="android.permission.WAKE_LOCK" />

在日志中没有错误,这是在应用程序关闭时记录的:

  1. 2020-08-09 18:28:31.772 1940-2694/system_process I/ActivityManager: Killing 5972:ego.emy.test/u0a85 (adj 900): remove task
  2. 2020-08-09 18:28:31.846 1940-2031/system_process W/InputDispatcher: channel 'e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
  3. 2020-08-09 18:28:31.846 1940-2031/system_process E/InputDispatcher: channel 'e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
  4. 2020-08-09 18:28:31.851 1940-4150/system_process I/WindowManager: WIN DEATH: Window{e5ad803 u0 ego.emy.test/ego.emy.test.MainActivity}
  5. 2020-08-09 18:28:31.851 1940-4150/system_process W/InputDispatcher: Attempted to unregister already unregistered input channel 'e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)'
  6. 2020-08-09 18:28:31.856 1795-2041/? W/SurfaceFlinger: Attempting to destroy on removed layer: AppWindowToken{4ba78aa token=Token{5a74f95 ActivityRecord{634d34c u0 ego.emy.test/.MainActivity t9}}}#0
  7. 2020-08-09 18:28:32.285 1940-2261/system_process I/ActivityManager: Force stopping ego.emy.test appid=10085 user=0: from pid 6295
  8. 之前,类似的任务在升级到 androidx 后正常工作。
英文:

androidx.work.Worker works only when the application is running. If the application terminates, the PeriodicWorkRequest stops performing periodic startup.

It is necessary to show notifications at a certain time interval for this I use PeriodicWorkRequest, when the application is running (even minimized) it works as it should, when the process dies there are no more notifications.

worker class

  1. import androidx.work.ExistingPeriodicWorkPolicy;
  2. import androidx.work.Operation;
  3. import androidx.work.PeriodicWorkRequest;
  4. import androidx.work.WorkManager;
  5. import androidx.work.WorkerParameters;
  6. import java.util.concurrent.TimeUnit;
  7. public class Worker extends androidx.work.Worker {
  8. public static final String NOTIFICATION_TAG = &quot;Notification&quot;;
  9. public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
  10. super(context, workerParams);
  11. Log.d(TAG, &quot;NotificationWorkerInit&quot;);
  12. }
  13. @NonNull
  14. @Override
  15. public Result doWork() {
  16. Log.d(TAG, &quot;doWork: START&quot;);
  17. Notification.showNotification(getApplicationContext());
  18. return Result.success();
  19. }
  20. public static void doNotifications(Context context, int quantityPerDay) {
  21. if (quantityPerDay &gt; 0) {
  22. startNotifications(context, quantityPerDay);
  23. } else {
  24. stopNotifications(context);
  25. }
  26. }
  27. private static void startNotifications(Context context, int interval) {
  28. int minInterval = 1;
  29. PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
  30. .Builder(Worker.class, interval, TimeUnit.SECONDS, minInterval, TimeUnit.SECONDS)
  31. .addTag(NOTIFICATION_TAG)
  32. .build();
  33. Log.d(TAG, &quot;startNotificationsService: tag &quot; + notificationsWorker.getTags());
  34. Log.d(TAG, &quot;startNotificationsService: id &quot; + notificationsWorker.getId());
  35. WorkManager workManager = WorkManager.getInstance(context);
  36. Operation enqueue = workManager.enqueueUniquePeriodicWork(NOTIFICATION_TAG,
  37. ExistingPeriodicWorkPolicy.REPLACE, notificationsWorker);
  38. }
  39. private static void stopNotifications(Context context) {
  40. WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_TAG);
  41. Log.d(TAG, &quot;stopNotifications: &quot;);
  42. }
  43. }

dependencies build.gradle (app)

  1. dependencies {
  2. implementation fileTree(dir: &#39;libs&#39;, include: [&#39;*.jar&#39;])
  3. implementation &#39;androidx.appcompat:appcompat:1.2.0&#39;
  4. implementation &#39;androidx.constraintlayout:constraintlayout:1.1.3&#39;
  5. implementation &#39;androidx.recyclerview:recyclerview:1.1.0&#39;
  6. // implementation &#39;org.jetbrains:annotations-java5:15.0&#39;
  7. implementation &#39;androidx.work:work-runtime:2.4.0&#39;
  8. implementation &#39;com.github.judemanutd:autostarter:1.0.8&#39;
  9. testImplementation &#39;junit:junit:4.13&#39;
  10. androidTestImplementation &#39;androidx.test.ext:junit:1.1.1&#39;
  11. androidTestImplementation &#39;androidx.test.espresso:espresso-core:3.2.0&#39;
  12. }

manifest permission (service, receiver no)

  1. &lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot; /&gt;
  2. &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;
  3. &lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot;/&gt;

There are no errors in the Log, this is what it writes when the application is closed:

  1. 2020-08-09 18:28:31.772 1940-2694/system_process I/ActivityManager: Killing 5972:ego.emy.test/u0a85 (adj 900): remove task
  2. 2020-08-09 18:28:31.846 1940-2031/system_process W/InputDispatcher: channel &#39;e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)&#39; ~ Consumer closed input channel or an error occurred. events=0x9
  3. 2020-08-09 18:28:31.846 1940-2031/system_process E/InputDispatcher: channel &#39;e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)&#39; ~ Channel is unrecoverably broken and will be disposed!
  4. 2020-08-09 18:28:31.851 1940-4150/system_process I/WindowManager: WIN DEATH: Window{e5ad803 u0 ego.emy.test/ego.emy.test.MainActivity}
  5. 2020-08-09 18:28:31.851 1940-4150/system_process W/InputDispatcher: Attempted to unregister already unregistered input channel &#39;e5ad803 ego.emy.test/ego.emy.test.MainActivity (server)&#39;
  6. 2020-08-09 18:28:31.856 1795-2041/? W/SurfaceFlinger: Attempting to destroy on removed layer: AppWindowToken{4ba78aa token=Token{5a74f95 ActivityRecord{634d34c u0 ego.emy.test/.MainActivity t9}}}#0
  7. 2020-08-09 18:28:32.285 1940-2261/system_process I/ActivityManager: Force stopping ego.emy.test appid=10085 user=0: from pid 6295

Previously, similar tasks worked after upgrading to androidx problems started

答案1

得分: 1

这是我在官方文档上找到的信息 -

WorkManager是一个API,它使得调度可延迟、异步的任务变得容易,即使应用退出或 设备重新启动,这些任务也有望运行

我认为您的PeriodicWorkRequest之所以无法正常工作,是因为您使用了不正确的时间间隔。

注意:可以定义的最小重复间隔为15分钟(更多信息

  1. PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
  2. .Builder(Worker.class, interval, TimeUnit.HOURS)
  3. .addTag(NOTIFICATION_TAG)
  4. .build();

将在每1小时内重复执行工作。

类似地,定期工作可以在每小时周期的最后15分钟运行。

  1. PeriodicWorkRequest periodicWorkRequest =
  2. new PeriodicWorkRequest.Builder(Worker.class,
  3. 1, TimeUnit.HOURS,
  4. 15, TimeUnit.MINUTES)
  5. .build();

祝编程愉快!

英文:

Well this what I found on official documentation -

> WorkManager is an API that makes it easy to schedule deferrable,
> asynchronous tasks that are expected to run even if the app exits or
> the device restarts.

I believe your PeriodicWorkRequest is not working for you because you are creating PeriodicWorkRequest with incorrect time interval.

> Note: The minimum repeat interval that can be defined is 15 minutes (more info)

  1. PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
  2. .Builder(Worker.class, interval, TimeUnit.HOURS)
  3. .addTag(NOTIFICATION_TAG)
  4. .build();

Will repeat work in every 1 hours.

Similary periodic work that can run during the last 15 minutes of every one hour period.

  1. PeriodicWorkRequest periodicWorkRequest =
  2. new PeriodicWorkRequest.Builder(Worker.class,
  3. 1, TimeUnit.HOURS,
  4. 15, TimeUnit.MINUTES)
  5. .build();

Happy Coding !

huangapple
  • 本文由 发表于 2020年8月9日 22:46:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63327693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定