1

我有一个应用程序应该每 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();
        }

我正在使用带有 Android Pie(SDK 28)的小米 miA2 androidOne 设备。还有一些其他的事情让我感到困扰:

  • 我可以做些什么来知道我的 WorkManager 是否正在运行?其他只需等待 2 小时并希望收到通知。我实际上尝试过类似的方法,让我的手机连接到电脑并不时检查 android studio 的 logcat。它确实在实际调用工作人员时运行所有日志,但我认为这不是测试它的正确方法,或者是吗?
  • 在上面的代码中,每次打开应用程序时都会setDailyNotifier()调用。onCreate()是不是错了?不应该有一些唯一的 idWorkRequest和一个检查函数,比如WorkManger.isRequestRunning(request.getID)它可以让我们检查一个工人是否已经在给定的任务上?如果这是一个例子AsyncTask,那么男孩我们会一团糟。

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

4

2 回答 2

2

几点评论:
WorkManager 的最小周期间隔为 15 分钟,并且不保证在精确的时间执行您的任务。您可以在此博客上阅读更多相关信息。

当您使用 WorkManager 安排任务时,您在较新的 Android 版本上遇到的所有常见背景限制仍然适用。WorkManager 保证即使应用被杀死或者设备被重新启动也能执行任务,但不能保证准确执行。

当您的应用程序被终止时,有一条关于重新安排任务的说明。一些 OEM 对操作系统和 Launcher 应用程序进行了修改,导致 WorkManager 无法完成这些功能。

这是问题跟踪器的讨论

是的,即使手机是中国手机也是如此。
我们遇到的唯一问题是一些中国原始设备制造商将刷卡从最近删除视为强制停止的情况。发生这种情况时,WorkManager 将在下次启动应用程序时重新安排所有待处理的作业。鉴于这是违反 CDD 的行为,WorkManager 没有太多可以做的,因为它有一个客户端库。

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

于 2019-01-05T17:57:21.353 回答
0

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

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

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

于 2019-01-13T17:26:03.293 回答