Реализация уведомлений в Android приложении
Необходимо в приложении реализовать вывод уведомлений с периодичностью и временем, который устанавливает пользователь.
Например пользователь выбрал частоту "Ежедневно" и время 09:00. Чтобы уведомление выводилось в это время.
Приложение типа учет финансов, но мне нужно чтобы уведомления приходили в точно указанное время (если даже приложение было выгружено из памяти, устройство перезапущено).
Какими методами такое реализуют? Пытался реализовать через WorkManager но после перезагрузки устройства уведомления не приходили. Пока важно понять какие механизмы для этого используют (для вывода уведомлений точно в указанное время)
Ответы (1 шт):
Переведено из этого ответа от Shia G
Вам нужно использовать BroadcastReceiver
Из-за того, что он может работать только на короткое время,
лучше использовать intent service, вот пример как это сделать:
При обработке
Broadcast, приложение получает фиксированное время (менее 10 секунд) чтобы выполнить задачуВ противном случае, оно считается некорректно работающим, и процесс сразу переводиться в фоновый режим для заверешния, если необходима память
Вот класс broadcast recevier'а:
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Intent intent1 = new Intent(context, MyNewIntentService.class);
context.startService(intent1);
}
}
Добавьте его в манифест:
<receiver
android: name=".MyReceiver"
android: enabled="true"
android: exported="false" >
</receiver>
Вот класс intent service'а:
public class MyNewIntentService extends IntentService {
private static final int NOTIFICATION_ID = 3;
public MyNewIntentService() {
super("MyNewIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle("My Title");
builder.setContentText("This is the Body");
builder.setSmallIcon(R.drawable.whatever);
Intent notifyIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 2, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Нужно, чтобы иметь возможность запустить свою activity из уведомления
builder.setContentIntent(pendingIntent);
Notification notificationCompat = builder.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
managerCompat.notify(NOTIFICATION_ID, notificationCompat);
}
}
И опять же, добавьте его в манифест:
<service
android: name=".MyNewIntentService"
android: exported="false" >
</service>
Далее добавьте вашей activity alarm manager чтобы запускать broadcast receiver в определённое время
Используем метод AlarmManager'а setExactAndAllowWhileIdle(), чтобы повторять уведомление внутри broadcast receiver'а
(Его нужно добавить в onReceive)
Примечание: в оригинальном ответе используется способ с методом
setRepeating(), который, как я узнал, сейчас считается устаревшим, вместо него будет использоватьсяsetExactAndAllowWhileIdle(), а старый способ будет закомментирован
В примере ниже activity будет запускаться каждый день:
Intent notifyIntent = new Intent(this,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, NOTIFICATION_REMINDER_NIGHT, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT
);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Старый способ
// alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 60 * 24, pendingIntent);
// Новый способ
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000 * 60 * 60 * 24, pendingIntent
);
Надеюсь это Вам поможет