#android #kotlin #android-notifications #alarmmanager
#Android #kotlin #android-уведомления #AlarmManager
Вопрос:
Я сталкиваюсь с проблемой при планировании нескольких (до 14) уведомлений с помощью AlarmManager. Проблема в том, что уведомления случайным образом отсутствуют (особенно когда отладочный кабель не подключен). Например, запускаются первые три уведомления, и после этих уведомлений ни одно из запланированных уведомлений больше не запускается, пока вы не измените расписание уведомлений. Кажется, это из-за количества уведомлений, но я не уверен на 100%.
Ниже вы можете найти мои функции для планирования уведомлений (уведомления о тревоге и перед сном);
private fun createNotificationChannel(name: String, descriptionText: String, id: String, setSound:Boolean)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(id, name, importance).apply {
description = descriptionText
}
val audioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
if (setSound)
{
channel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE "://" m_context.packageName "/" m_ringtone), audioAttributes)
}
(m_context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).createNotificationChannel(channel)
}
}
private fun createBedTimeNotificationChannel()
{
createNotificationChannel(BEDTIME_NOTIFICATION_CHANNEL_NAME, BEDTIME_NOTIFICATION_CHANNEL_DESCRIPTION, BEDTIME_NOTIFICATION_CHANNEL, false)
}
private fun createWakeUpNotificationChannel()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
for (channel in (m_context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notificationChannels)
{
if (channel.id.contains(WAKE_UP_ALARM_NOTIFICATION_CHANNEL))
{
(m_context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).deleteNotificationChannel(channel.id)
}
}
m_randomNumber = Random().nextLong()
createNotificationChannel(WAKE_UP_NOTIFICATION_CHANNEL_NAME, WAKE_UP_NOTIFICATION_CHANNEL_DESCRIPTION, WAKE_UP_ALARM_NOTIFICATION_CHANNEL m_randomNumber, true)
}
}
fun configureAlarmNotification(ringtone: Int, alarmTime: Int, snooze: Boolean, days: BooleanArray)
{
m_ringtone = ringtone
createWakeUpNotificationChannel()
for ((index, alarmOn) in days.withIndex())
{
if (alarmOn)
{
val builder = getWakeUpAlarmBuilder()
val intent = Intent(m_context, CMainActivity::class.java)
val activity = PendingIntent.getActivity(m_context, WAKE_UP_NOTIFICATION_ID_START index 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(activity)
if (snooze)
{
val snoozeIntent = Intent(m_context, CSleepPlannerService::class.java).apply {
putExtra(ACTION, ACTION_SNOOZE)
putExtra(NOTIFICATION_ID, WAKE_UP_NOTIFICATION_ID_START index 1)
putExtra(NOTIFICATION, builder.build())
}
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(m_context, SNOOZE_PRESSED_NOTIFICATION_ID index 1, snoozeIntent, 0)
builder.addAction(R.drawable.alarm_bel_icon, m_context.getString(R.string.snooze), snoozePendingIntent)
}
val notification = builder.build()
val calendar = Calendar.getInstance()
val currentTimeInMillis = calendar.timeInMillis
calendar[Calendar.DAY_OF_WEEK] = convertWeekday(index)
calendar[Calendar.HOUR_OF_DAY] = alarmTime / 60
calendar[Calendar.MINUTE] = alarmTime % 60
calendar[Calendar.SECOND] = 0
if (calendar.timeInMillis <= currentTimeInMillis)
{
calendar.timeInMillis = NUMBER_OF_MILLIS_IN_WEEK
}
val pendingIntent = getPendingIntent(calendar.timeInMillis, WAKE_UP_NOTIFICATION_ID_START index 1, notification, ACTION_NOTIFICATION, PendingIntent.FLAG_UPDATE_CURRENT)
(m_context.getSystemService(ALARM_SERVICE) as AlarmManager).setExact(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
}
}
val calendar = Calendar.getInstance()
m_alarmWithSoundEnabledWithinADay.postValue((m_preferences.isAlarmWithSoundEnabled() amp;amp; isAlarmEnabled(calendar[Calendar.HOUR_OF_DAY] * 60 calendar[Calendar.MINUTE], m_preferences.getAlarmTime(), calendar[Calendar.DAY_OF_WEEK])))
}
fun configureBedTimeNotification(bedTime: Int, bedTimeSetting: Int, days: BooleanArray)
{
for ((index, alarmOn) in days.withIndex())
{
if (alarmOn)
{
val builder = NotificationCompat.Builder(m_context, BEDTIME_NOTIFICATION_CHANNEL).apply {
setContentTitle(m_context.getString(R.string.bedtime_notification_tile))
when (BedTimeNotificationSetting_e.fromInt(bedTimeSetting))
{
BedTimeNotificationSetting_e.AT_BED_TIME -> setContentText(m_context.getString(R.string.bedtime_notification_at_bedtime))
BedTimeNotificationSetting_e.TEN_MINUTES_BEFORE -> setContentText(m_context.getString(
R.string.bedtime_notification_description_ten
))
BedTimeNotificationSetting_e.THIRTY_MINUTES_BEFORE -> setContentText(m_context.getString(R.string.bedtime_notification_description_thirty))
BedTimeNotificationSetting_e.FORTYFIVE_MINUTES_BEFORE -> setContentText(m_context.getString(R.string.bedtime_notification_description_fortyfive))
BedTimeNotificationSetting_e.SIXTY_MINUTES_BEFORE -> setContentText(m_context.getString(R.string.bedtime_notification_description_sixty))
}
setAutoCancel(true)
setSmallIcon(R.drawable.alarm_icon)
priority = NotificationCompat.PRIORITY_HIGH
}
val intent = Intent(m_context, CMainActivity::class.java)
val activity = PendingIntent.getActivity(m_context, BEDTIME_NOTIFICATION_ID_START index 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
builder.setContentIntent(activity)
val notification = builder.build()
val calendar = Calendar.getInstance()
val currentTimeInMillis = calendar.timeInMillis
calendar[Calendar.DAY_OF_WEEK] = convertWeekday(index)
calendar[Calendar.HOUR_OF_DAY] = bedTime / 60
calendar[Calendar.MINUTE] = bedTime % 60
calendar[Calendar.SECOND] = 0
var newBedTime = calendar.timeInMillis - (bedTimeSetting * 60 * 1000)
if (newBedTime <= currentTimeInMillis)
{
newBedTime = NUMBER_OF_MILLIS_IN_WEEK
}
val pendingIntent = getPendingIntent(newBedTime, BEDTIME_NOTIFICATION_ID_START index 1, notification, ACTION_NOTIFICATION, PendingIntent.FLAG_UPDATE_CURRENT)
(m_context.getSystemService(ALARM_SERVICE) as AlarmManager).setExact(AlarmManager.RTC_WAKEUP, newBedTime, pendingIntent)
}
}
}
private fun getPendingIntent(calendarTime: Long = 0, notificationId: Int, notification: Notification? = null, action: String, flag: Int) : PendingIntent?
{
val notificationIntent = Intent(m_context, this::class.java)
notificationIntent.putExtra(ACTION, action)
notificationIntent.putExtra(NOTIFICATION_ID, notificationId)
notificationIntent.putExtra(NOTIFICATION, notification)
notificationIntent.putExtra(ALARM_TIME, calendarTime)
return PendingIntent.getBroadcast(m_context, notificationId, notificationIntent, flag)
}
Что может быть причиной этого?
Ответ №1:
Трудно точно знать, что может быть не так. В зависимости от версии системы Android может решить подождать / отложить / группировать уведомления. Оставшийся заряд батареи также влияет на решение показать уведомление.
Я вижу, что вы используете setPriority
в конструкторе уведомлений HIGH
значение. Это должно работать для Android <api 26. Для более новых версий будет setImportance
учитываться канал уведомлений
- При создании канала попробуйте использовать High importance
val importance = NotificationManager.IMPORTANCE_HIGH
// отредактируйте свой код следующим образом в createNotificationChannel, который вы используете в настоящее время DEFAULT
- убедитесь, что в телефоне, который вы используете для тестирования, нет такой опции, как экономия заряда батареи или что-то еще.
Ответ №2:
Я исправил проблему с настройкой уведомлений о пробуждении с помощью функции setAlarmClock из AlarmManager.