Periodic Worker 在 AndroidX 中

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

Periodic Worker in androidx

问题

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

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

工作类

import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.Operation;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.WorkerParameters;
import java.util.concurrent.TimeUnit;

public class Worker extends androidx.work.Worker {

    public static final String NOTIFICATION_TAG = "Notification";

    public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
       super(context, workerParams);
       Log.d(TAG, "NotificationWorkerInit");
    }

   @NonNull
   @Override
   public Result doWork() {
      Log.d(TAG, "doWork: START");
      Notification.showNotification(getApplicationContext());
      return Result.success();
   }

   public static void doNotifications(Context context, int quantityPerDay) {
      if (quantityPerDay > 0) {
          startNotifications(context, quantityPerDay);
      } else {
          stopNotifications(context);
      }
   }

   private static void startNotifications(Context context, int interval) {
       int minInterval = 1;
       PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
              .Builder(Worker.class, interval, TimeUnit.SECONDS, minInterval, TimeUnit.SECONDS)
              .addTag(NOTIFICATION_TAG)
              .build();
       Log.d(TAG, "startNotificationsService: tag " + notificationsWorker.getTags());
       Log.d(TAG, "startNotificationsService: id  " + notificationsWorker.getId());

       WorkManager workManager = WorkManager.getInstance(context);
       Operation enqueue = workManager.enqueueUniquePeriodicWork(NOTIFICATION_TAG, 
            ExistingPeriodicWorkPolicy.REPLACE, notificationsWorker);
   }

   private static void stopNotifications(Context context) {
      WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_TAG);
      Log.d(TAG, "stopNotifications: ");
   }
}

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

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

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

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

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

2020-08-09 18:28:31.772 1940-2694/system_process I/ActivityManager: Killing 5972:ego.emy.test/u0a85 (adj 900): remove task
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
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!
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}
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)'
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
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
之前,类似的任务在升级到 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

import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.Operation;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.WorkerParameters;
import java.util.concurrent.TimeUnit;
public class Worker extends androidx.work.Worker {
public static final String NOTIFICATION_TAG = &quot;Notification&quot;;
public Worker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
Log.d(TAG, &quot;NotificationWorkerInit&quot;);
}
@NonNull
@Override
public Result doWork() {
Log.d(TAG, &quot;doWork: START&quot;);
Notification.showNotification(getApplicationContext());
return Result.success();
}
public static void doNotifications(Context context, int quantityPerDay) {
if (quantityPerDay &gt; 0) {
startNotifications(context, quantityPerDay);
} else {
stopNotifications(context);
}
}
private static void startNotifications(Context context, int interval) {
int minInterval = 1;
PeriodicWorkRequest notificationsWorker = new PeriodicWorkRequest
.Builder(Worker.class, interval, TimeUnit.SECONDS, minInterval, TimeUnit.SECONDS)
.addTag(NOTIFICATION_TAG)
.build();
Log.d(TAG, &quot;startNotificationsService: tag &quot; + notificationsWorker.getTags());
Log.d(TAG, &quot;startNotificationsService: id  &quot; + notificationsWorker.getId());
WorkManager workManager = WorkManager.getInstance(context);
Operation enqueue = workManager.enqueueUniquePeriodicWork(NOTIFICATION_TAG, 
ExistingPeriodicWorkPolicy.REPLACE, notificationsWorker);
}
private static void stopNotifications(Context context) {
WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_TAG);
Log.d(TAG, &quot;stopNotifications: &quot;);
}
}

dependencies build.gradle (app)

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

manifest permission (service, receiver no)

&lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;
&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:

2020-08-09 18:28:31.772 1940-2694/system_process I/ActivityManager: Killing 5972:ego.emy.test/u0a85 (adj 900): remove task
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
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!
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}
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;
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
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分钟(更多信息

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

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

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

PeriodicWorkRequest periodicWorkRequest =
           new PeriodicWorkRequest.Builder(Worker.class,
                   1, TimeUnit.HOURS,
                   15, TimeUnit.MINUTES)
               .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)

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

Will repeat work in every 1 hours.

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

PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(Worker.class,
1, TimeUnit.HOURS,
15, TimeUnit.MINUTES)
.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:

确定