定期工作经理在未充电或屏幕关闭时未在android pie上显示通知

定期工作经理在未充电或屏幕关闭时未在android pie上显示通知,android,android-workmanager,xiaomi,Android,Android Workmanager,Xiaomi,我有一个应用程序,应该显示通知每2小时,并应停止,如果用户已经采取行动的notif。由于后台服务现在已经成为历史,因此我考虑使用WorkManager(“android.arch.work:work-runtime:1.0.0-beta01”)实现同样的功能 我的问题是,虽然work manager在应用程序运行时成功地显示了通知,但在以下情况下它不会一致地显示通知(我将检查一致性的时间跨度从2小时缩短为2分钟): 当应用程序从后台被删除时 设备处于屏幕关闭状态 状态设备处于未连接状态(即未充

我有一个应用程序,应该显示通知每2小时,并应停止,如果用户已经采取行动的notif。由于后台服务现在已经成为历史,因此我考虑使用WorkManager(
“android.arch.work:work-runtime:1.0.0-beta01”
)实现同样的功能

我的问题是,虽然work manager在应用程序运行时成功地显示了通知,但在以下情况下它不会一致地显示通知(我将检查一致性的时间跨度从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);

    }
    ....
}
这是worker类(我可以发布
showNotif(…)
setNotificationChannel(…)
,如果它们可能出错的话):

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

  • 我能做些什么来知道我的WorkManager是否正在运行?另一种是等待2个小时,希望得到通知。实际上,我试过类似的方法,让我的手机与pc保持连接,并时不时地检查android studio的logcat。它确实会在实际调用worker时运行所有日志,但我认为这不是测试它的正确方法,或者是吗
  • 在上面的代码中,每次打开应用程序时,都会从onCreate()调用setDailNotifier()。是不是错了?每个
    WorkRequest
    是否应该有一些唯一的id,以及像
    WorkManger.isRequestRunning(request.getID)
    这样的检查函数,它可以让我们检查一个工人是否已经在给定的任务中??如果这是
    AsyncTask
    的情况,那么我们就会一团糟
我还检查了@commonware关于屏幕关闭时wakelock的回答,但我记得工作经理确实在可用时在内部使用alarm manager。那么我在这里遗漏了什么呢?

很少有评论:
WorkManager的最小周期间隔为15分钟,不保证在精确的时间执行任务。您可以在上阅读更多关于此的信息

当您使用WorkManager计划任务时,您在较新的Android版本上的所有常规后台限制仍然是相关的。WorkManager保证即使应用程序被终止或设备被重述,任务也会被执行,但它不能保证任务的准确执行

有一个注意事项是,当你的应用程序被终止时,任务将被重新安排。一些OEM对操作系统和Launcher应用程序进行了修改,使WorkManager无法完成这些功能

:

是的,即使手机是中国手机也是如此。
我们遇到的唯一一个问题是,一些中国原始设备制造商将最近的swipe解雇视为强制停止。当这种情况发生时,WorkManager将在下次应用程序启动时重新安排所有挂起的作业。考虑到这是一个CDD冲突,WorkManager在拥有一个客户机库的情况下所能做的就不多了

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


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

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

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


WorkManager的最小周期间隔为15分钟,并且不保证在精确的时间执行任务
因此,有什么方法可以测试此类模块?你能解释一下这个15分钟的最小周期间隔吗?比如,如果用户必须制作一个聊天应用程序,每2分钟从服务器上检查一条收到的消息,该怎么办?对于示例应用程序,最好的选择是从服务器上推送通知,而不是每x分钟轮询一次新消息。这对设备的电池来说要好得多。我在安卓pie OnePlus手机上每15分钟测试一次,但我注意到现在已经超过20分钟了,但在第一次有人知道如何让Perioodc管理器工作后,通知就没有显示出来
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();
        }