定期工作经理不显示通知时,不充电或屏幕关闭android馅饼



我有一个应用程序,它应该每2小时显示一次通知,如果用户已经对通知采取了行动,它应该停止。由于后台服务现在已经成为历史,所以我考虑使用WorkManager("android.arch.work:work-runtime:1.0.0-beta01")进行同样的处理。

我的问题是,尽管工作经理在应用程序运行时成功地显示了通知,但在以下情况下它不会一致地显示通知(我将时间跨度从2小时缩短到2分钟以检查一致性):

  • 当应用程序从后台被杀死时
  • 设备处于屏幕关闭状态
  • 状态设备处于拔出状态(即未充电)

所谓一致性,我的意思是通知在给定的时间跨度内至少显示一次。在2分钟的时间跨度内,通知频率从每4分钟一次变为完全不显示任何通知。2个小时的时间跨度(我真正想要的时间跨度),已经4个小时了,我没有收到任何通知。这是我用来调用WorkManger的代码:

public class CurrentStreakActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setDailyNotifier();
...
}
private void setDailyNotifier() {
Constraints.Builder constraintsBuilder = new Constraints.Builder();
constraintsBuilder.setRequiresBatteryNotLow(false);
constraintsBuilder.setRequiredNetworkType(NetworkType.NOT_REQUIRED);
constraintsBuilder.setRequiresCharging(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
constraintsBuilder.setRequiresDeviceIdle(false);
}
Constraints constraints =constraintsBuilder.build();

PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
.Builder(PeriodicNotifyWorker.class, 2, TimeUnit.HOURS);
builder.setConstraints(constraints);
WorkRequest request = builder.build();
WorkManager.getInstance().enqueue(request);
}
....
}

这是工人类(如果showNotif(..)setNotificationChannel(...)可能有错误,我也可以发布它们):

public class PeriodicNotifyWorker extends Worker {
private static final String TAG = "PeriodicNotifyWorker";
public PeriodicNotifyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
Log.e(TAG, "PeriodicNotifyWorker: constructor called" );
}
@NonNull
@Override
public Result doWork() {
//        Log.e(TAG, "doWork: called" );
SharedPreferences sp =
getApplicationContext().getSharedPreferences(Statics.SP_FILENAME, Context.MODE_PRIVATE);
String lastcheckin = sp.getString(Statics.LAST_CHECKIN_DATE_str, Statics.getToday());
//        Log.e(TAG, "doWork: checking shared preferences for last checkin:"+lastcheckin );
if (Statics.compareDateStrings(lastcheckin, Statics.getToday()) == -1) {
Log.e(TAG, "doWork: last checkin is smaller than today's date, so calling creating notification" );
return createNotificationWithButtons(sp);
}
else {
Log.e(TAG, "doWork: last checkin is bigger than today's date, so no need for notif" );
return Result.success();
}
}

private Result createNotificationWithButtons(SharedPreferences sp) {
NotificationManager manager =
(NotificationManager) getApplicationContext().getSystemService((NOTIFICATION_SERVICE));
String channel_ID = "100DaysOfCode_ID";
if (manager != null) {
setNotificationChannel(manager,channel_ID);
showNotif(manager, channel_ID, sp);
return Result.success();
}
else {
return Result.failure();
}

我正在使用安卓派(SDK 28)的小米miA2安卓一体机。还有其他一些事情困扰着我:

  • 如果我的WorkManager正在运行,我可以做些什么?其他人只需等待2个小时,并希望收到通知。事实上,我试过这样的方法,把手机连接到电脑上,时不时地查看安卓工作室的logcat。当实际调用worker时,它确实会运行所有日志,但我认为这不是测试它的正确方法,或者是这样吗
  • 在上面的代码中,每次打开应用程序时都会从onCreate()调用setDailyNotifier()。是不是错了?是否应该为每个WorkRequest都有一些唯一的id和像WorkManger.isRequestRunning(request.getID)这样的检查函数,让我们检查工作人员是否已经在执行给定的任务??如果这是AsyncTask的情况,那么天哪,我们会一团糟

我也在这里查看了@commonsware关于屏幕关闭时唤醒锁定的回答,但我记得工作经理在可用时确实在内部使用了报警管理器。那么我在这里错过了什么?

很少有评论:
WorkManager的最小周期间隔为15分钟,不能保证在精确的时间执行任务。你可以在这个博客上阅读更多关于这方面的内容。

当你使用WorkManager来安排任务时,你在新的Android版本上的所有常见背景限制仍然相关。WorkManager保证即使应用程序被终止或设备被重述,任务也会被执行,但它不能保证准确执行。

当你的应用程序被终止时,有一条关于任务被重新安排的注释。一些OEM对操作系统和Launcher应用程序进行了修改,使WorkManager无法实现这些功能。

以下是问题解决者的讨论:

是的,即使手机是中国手机也是如此
我们遇到的唯一问题是,一些中国原始设备制造商将Recents的"刷到开除"视为强制停止。当这种情况发生时,WorkManager将在应用程序下次启动时重新安排所有挂起的作业。考虑到这是违反CDD的行为,考虑到WorkManager有一个客户端库,它就没有什么可做的了。

此外,如果设备制造商决定修改库存Android以强制停止应用程序,WorkManager将停止工作(JobScheduler、警报器、广播接收器等也将停止工作)。没有办法解决这个问题。不幸的是,一些设备制造商会这样做,因此在这种情况下,WorkManager将停止工作,直到下次启动应用程序。

到目前为止,我已经安装了这个应用程序8天了,我可以确认代码是正确的,并且应用程序运行良好。正如pfmaggi所说,工作经理安排工作的最短时间间隔是15分钟,因此WorkManager在我的测试条件下(2分钟)按预期工作的可能性较小。以下是我的一些其他观察结果:

  • 就像我在问题中所说的,即使我已经超过了2小时的重复间隔,我也无法在4小时内收到通知。这是因为弹性时间。我通过了15分钟的弹性时间,现在它显示了正确时间间隔之间的通知。所以我会把pfmaggi的答案标记为正确
  • WorkManager.getInstance().enqueueUniqueWork(request,..)代替WorkManager.getInstance().enqueue(request)可以解决重复工作请求的问题

  • 我仍然无法找到一种方法来测试我所描述的工作经理。

最新更新