У меня есть приложение, которое должно показывать уведомление каждые 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();
}
Я использую устройство xiaomi miA2 androidOne с Android Pie (SDK 28). Меня беспокоит еще несколько вещей:
- Что я могу сделать, чтобы узнать, работает ли мой WorkManager? Другие, которые просто ждут 2 часа и надеются на уведомление. Я на самом деле пробовал что-то подобное, держал телефон подключенным к компьютеру и время от времени проверял logcat от android studio. Он запускает все журналы, когда рабочий действительно вызывается, но я не думаю, что это правильный способ проверить это, или это так?
- В приведенном выше коде
setDailyNotifier()
вызывается из onCreate()
каждый раз, когда приложение открывается. Разве это не так? не должно быть какого-то уникального идентификатора для каждого WorkRequest
и функции проверки, такой как WorkManger.isRequestRunning(request.getID)
, которая позволила бы нам проверить, выполняет ли работник уже заданное задание? Если это был случай AsyncTask
, то мы будет беспорядок.
Я также проверил ответ @ commonsware здесь о wakelock, когда экран выключен, но я помню, что диспетчер работ использует диспетчер тревог внутри, когда он доступен. Так чего мне здесь не хватает?