Я хочу установить уведомление на каждый день, в выбранные пользователем часы и минуты, но проблема в том, что иногда оно получает уведомление вовремя, а иногда задерживается с задержкой в 10, 20, 30, 40 секунд, а также проверьте, что сегодня время прошло или нет; если да, я не хочу показывать уведомление
Функция установки уведомлений
private fun scheduleNotification(context: Context, hour: Int, minute: Int) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
if (before(Calendar.getInstance())) {
add(Calendar.DATE, 1)
}
}
alarmManager.cancel(pendingIntent)
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
pendingIntent
)
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
}
private fun createNotificationChannel(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Workout Reminder Channel"
val descriptionText = "Channel for workout reminders"
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
companion object {
const val CHANNEL_ID = "workout_reminder_channel"
}
Широковещательный приемник
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val today = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
LocalDate.now()
} else {
TODO("VERSION.SDK_INT < O")
}
val mainIntent = Intent(context, MainActivity::class.java)
mainIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(
context,
0,
mainIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notification = NotificationCompat.Builder(context, ProfileViewModel.CHANNEL_ID)
.setSmallIcon(R.drawable.img_fitness1)
.setContentTitle("Workout Reminder")
.setContentText("It's time for your workout! Time : ${formatDate(today)}")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.build()
notificationManager.notify(NOTIFICATION_ID, notification)
}
companion object {
const val NOTIFICATION_ID = 1
}
}
Пожалуйста, ознакомьтесь с официальной документацией о планировании будильников.
В Android есть два типа будильников:
Если мы проверим документацию setRepeated, мы обнаружим следующую информацию:
Примечание. Начиная с API 19, все повторяющиеся сигналы тревоги являются неточными. Если вашему приложению необходимы точные сроки доставки, оно должно использовать одноразовые точные сигналы тревоги, каждый раз перепланируя, как описано выше. Устаревшие приложения, у которых targetSdkVersion старше API 19, по-прежнему будут считать все свои сигналы тревоги, включая повторяющиеся сигналы тревоги, точными.
Поэтому в зависимости от того, какие API-интерфейсы устройств вы хотите поддерживать, вам нужно будет использовать двухуровневый подход:
setRepeated
, и это будет точно.В вашем случае, если уведомление должно появиться в указанное пользователем время, вы можете использовать setAlarmClock
. Однако затем вам необходимо запланировать каждый следующий сигнал тревоги в вашем коде.
См. также этот вопрос о stackoverflow для справки.