Реализация уведомлений в Android приложении

Необходимо в приложении реализовать вывод уведомлений с периодичностью и временем, который устанавливает пользователь.

Например пользователь выбрал частоту "Ежедневно" и время 09:00. Чтобы уведомление выводилось в это время.

Приложение типа учет финансов, но мне нужно чтобы уведомления приходили в точно указанное время (если даже приложение было выгружено из памяти, устройство перезапущено).

Какими методами такое реализуют? Пытался реализовать через WorkManager но после перезагрузки устройства уведомления не приходили. Пока важно понять какие механизмы для этого используют (для вывода уведомлений точно в указанное время)


Ответы (1 шт):

Автор решения: LolPopGames

Переведено из этого ответа от 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 в определённое время

Используем метод AlarmManagersetExactAndAllowWhileIdle(), чтобы повторять уведомление внутри 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
);

Надеюсь это Вам поможет

→ Ссылка