不充电或屏幕关闭时,定期工作管理器未在 android 饼图上显示通知
Periodic Work manager not showing notification on android pie when not charging or screen off
我有一个应用程序应该每 2 小时显示一次通知,如果用户已经对通知采取行动,它应该停止。由于后台服务现在已经成为历史,我想到了使用 WorkManager ("android.arch.work:work-runtime:1.0.0-beta01"
) 来实现同样的目的。
我的问题是,虽然工作管理器在应用 运行ning 时成功显示通知,但在以下情况下它不会持续显示通知(我将时间跨度从 2 小时减少到2分钟检查一致性):
- 当应用程序从后台终止时。
- 设备处于屏幕关闭状态。
- state 设备处于拔出状态(即未充电)。
一致性是指通知在给定的时间跨度内至少显示一次。在 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);
}
....
}
这是工作人员 class(我也可以 post 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();
}
我正在使用小米 miA2 android一台设备 Android Pie(SDK 28)。还有其他一些困扰我的事情:
- 我怎样才能知道我的 WorkManager 是否 运行ning?其他只需等待 2 小时并希望收到通知。我实际上尝试过类似的方法,让我的 phone 连接到电脑并时不时检查 android 工作室的 logcat。它 运行 实际调用工作人员时的所有日志,但我认为这不是测试它的正确方法,是吗?
- 在上面的代码中,每次打开应用程序时,都会从
onCreate()
调用 setDailyNotifier()
。是不是错了?每个 WorkRequest
不应该有一些唯一的 ID 和一个像 WorkManger.isRequestRunning(request.getID)
这样的检查函数,它可以让我们检查一个工人是否已经在给定的任务上?如果这是 [=20 的情况=],那么天哪,我们会一团糟。
我还检查了@commonsware 关于屏幕关闭时唤醒锁的回答here,但我记得工作管理器在可用时确实在内部使用了警报管理器。那么我在这里缺少什么?
几条评论:
WorkManager 的最小周期间隔为 15 分钟,不保证在准确的时间执行您的任务。您可以在 this blog.
上阅读更多相关信息
当您使用 WorkManager 安排任务时,您在较新的 Android 版本中遇到的所有常见背景限制仍然相关。 WorkManager 保证即使应用被杀死或设备被重置也会执行任务,但它不能保证准确执行。
有一条关于在您的应用被终止时重新安排任务的说明。某些 OEM 已对 OS 和 Launcher 应用程序进行了修改,以防止 WorkManager 能够完成这些功能。
Here's the issuetracker discussion:
Yes, it's true even when the phone is a Chinese phone.
The only issue that we have come across is the case where some Chinese OEMs treat swipe to dismiss from Recents as a force stop. When that happens, WorkManager will reschedule all pending jobs, next time the app starts up. Given that this is a CDD violation, there is not much more that WorkManager can do given its a client library.
To add to this, if a device manufacturer has decided to modify stock Android to force-stop the app, WorkManager will stop working (as will JobScheduler, alarms, broadcast receivers, etc.). There is no way to work around this. Some device manufacturers do this, unfortunately, so in those cases WorkManager will stop working until the next time the app is launched.
截至目前,我已经安装此应用程序 8 天了,我可以确认代码 正确 并且应用程序运行良好。正如 pfmaggi 所说,工作经理安排工作的最短时间间隔为 15 分钟,因此 WorkManager
在我的测试条件下(2 分钟)按预期工作的可能性较小) 。以下是我的一些其他观察结果:
- 就像我在问题中所说的那样,即使我已经超过 2 小时的重复间隔,我也无法收到 4 小时的通知。这是因为 Flex Time。我通过了 15 分钟的弹性时间,现在它显示正确时间间隔之间的通知。所以我会将 pfmaggi 的回答标记为正确。
将WorkManager.getInstance().enqueue(request)
换成WorkManager.getInstance().enqueueUniqueWork(request,..)
可以解决重复工作请求的问题
我仍然无法按照我描述的方式找到测试工作管理器的方法。
我有一个应用程序应该每 2 小时显示一次通知,如果用户已经对通知采取行动,它应该停止。由于后台服务现在已经成为历史,我想到了使用 WorkManager ("android.arch.work:work-runtime:1.0.0-beta01"
) 来实现同样的目的。
我的问题是,虽然工作管理器在应用 运行ning 时成功显示通知,但在以下情况下它不会持续显示通知(我将时间跨度从 2 小时减少到2分钟检查一致性):
- 当应用程序从后台终止时。
- 设备处于屏幕关闭状态。
- state 设备处于拔出状态(即未充电)。
一致性是指通知在给定的时间跨度内至少显示一次。在 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);
}
....
}
这是工作人员 class(我也可以 post 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();
}
我正在使用小米 miA2 android一台设备 Android Pie(SDK 28)。还有其他一些困扰我的事情:
- 我怎样才能知道我的 WorkManager 是否 运行ning?其他只需等待 2 小时并希望收到通知。我实际上尝试过类似的方法,让我的 phone 连接到电脑并时不时检查 android 工作室的 logcat。它 运行 实际调用工作人员时的所有日志,但我认为这不是测试它的正确方法,是吗?
- 在上面的代码中,每次打开应用程序时,都会从
onCreate()
调用setDailyNotifier()
。是不是错了?每个WorkRequest
不应该有一些唯一的 ID 和一个像WorkManger.isRequestRunning(request.getID)
这样的检查函数,它可以让我们检查一个工人是否已经在给定的任务上?如果这是 [=20 的情况=],那么天哪,我们会一团糟。
我还检查了@commonsware 关于屏幕关闭时唤醒锁的回答here,但我记得工作管理器在可用时确实在内部使用了警报管理器。那么我在这里缺少什么?
几条评论:
WorkManager 的最小周期间隔为 15 分钟,不保证在准确的时间执行您的任务。您可以在 this blog.
当您使用 WorkManager 安排任务时,您在较新的 Android 版本中遇到的所有常见背景限制仍然相关。 WorkManager 保证即使应用被杀死或设备被重置也会执行任务,但它不能保证准确执行。
有一条关于在您的应用被终止时重新安排任务的说明。某些 OEM 已对 OS 和 Launcher 应用程序进行了修改,以防止 WorkManager 能够完成这些功能。
Here's the issuetracker discussion:
Yes, it's true even when the phone is a Chinese phone.
The only issue that we have come across is the case where some Chinese OEMs treat swipe to dismiss from Recents as a force stop. When that happens, WorkManager will reschedule all pending jobs, next time the app starts up. Given that this is a CDD violation, there is not much more that WorkManager can do given its a client library.To add to this, if a device manufacturer has decided to modify stock Android to force-stop the app, WorkManager will stop working (as will JobScheduler, alarms, broadcast receivers, etc.). There is no way to work around this. Some device manufacturers do this, unfortunately, so in those cases WorkManager will stop working until the next time the app is launched.
截至目前,我已经安装此应用程序 8 天了,我可以确认代码 正确 并且应用程序运行良好。正如 pfmaggi 所说,工作经理安排工作的最短时间间隔为 15 分钟,因此 WorkManager
在我的测试条件下(2 分钟)按预期工作的可能性较小) 。以下是我的一些其他观察结果:
- 就像我在问题中所说的那样,即使我已经超过 2 小时的重复间隔,我也无法收到 4 小时的通知。这是因为 Flex Time。我通过了 15 分钟的弹性时间,现在它显示正确时间间隔之间的通知。所以我会将 pfmaggi 的回答标记为正确。
将
WorkManager.getInstance().enqueue(request)
换成WorkManager.getInstance().enqueueUniqueWork(request,..)
可以解决重复工作请求的问题
我仍然无法按照我描述的方式找到测试工作管理器的方法。