我有一个应用程序,该应用程序每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 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);
}
....
}
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 androidOne设备与Android Pie(SDK 28)配合使用。还有其他一些令我困扰的事情:
setDailyNotifier()
中调用onCreate()
。是不是不对?是否应该为每个WorkRequest
都没有一个唯一的ID以及像WorkManger.isRequestRunning(request.getID)
这样的检查函数,它可以让我们检查工人是否已经在给定的任务上?如果这是{{1 }},那么男孩,我们将一团糟。 我还检查了@commonsware的答案here(如果您正在阅读此书,请注意@psons的忠实粉丝,先生,如果您正在阅读),但是我记得工作经理确实在其中使用了警报管理器。内部(如果有)。那我在这里想念什么?
答案 0 :(得分:1)
少量评论:
WorkManager的最小定期间隔为15分钟,并且不能保证在准确的时间执行您的任务。您可以在this blog上了解有关此内容的更多信息。
使用WorkManager安排任务时,在较新的Android版本上具有的所有通常的背景限制仍然有用。 WorkManager保证即使应用程序被杀死或设备已恢复也可以执行任务,但是它不能保证确切的执行。
关于您的应用程序被终止时要重新安排任务的注意事项之一。一些OEM对OS和Launcher应用程序进行了修改,以防止WorkManager能够完成这些功能。
Here's the issuetracker discussion:
是的,即使电话是中文电话也是如此。
我们遇到的唯一问题是一些中国OEM将轻击从“最近”中解雇为强制停止的情况。发生这种情况时,WorkManager将在下次启动应用程序时重新计划所有待处理的作业。鉴于这是CDD的违规行为,因此只要有一个客户端库,WorkManager便无能为力。此外,如果设备制造商决定修改库存的Android以强制停止应用程序,WorkManager将停止工作(JobScheduler,警报,广播接收器等也将停止工作)。没有办法解决此问题。不幸的是,某些设备制造商会这样做,因此在这种情况下,WorkManager将停止工作,直到下次启动该应用程序为止。
答案 1 :(得分:0)
截至目前,我已经在过去8天内安装了此应用,可以确认该代码正确并且该应用运行正常。如pfmaggi所述,工作经理安排工作的最短时间间隔为15分钟,因此WorkManager
在我的测试条件下(如2分钟)按预期工作的可能性较小)。这是我的其他一些观察结果:
可以通过将WorkManager.getInstance().enqueue(request)
替换为WorkManager.getInstance().enqueueUniqueWork(request,..)
我仍然找不到以我所描述的方式测试工作经理的方法。