Я использую AlarmManager для установки 2 разных повторяющихся сигналов. Один час срабатывает каждый час в минуту 59. Этот сигнал тревоги всегда работает правильно. Но другой сигнал тревоги, который запланирован каждые 5 минут, начинает работать должным образом в течение 1 или 2 часов. По истечении этого времени мой AlarmManager планирует тревогу, но она больше не срабатывает.
Я использую setExactAndAllowWhileIdle()
метод для планирования аварий.
Чтобы проверить, был ли будильник активирован или нет, я использую этот метод после вызова setExactAndAllowWhileIdle()
:
fun isAlarmActive(frameType: FrameType): Boolean{
val alarmIntent = getAlarmIntent(frameType)
alarmIntent.action = CUSTOM_INTENT
return PendingIntent.getBroadcast(ctx, 0, alarmIntent, PendingIntent.FLAG_NO_CREATE) != null
}
Я проверил этот метод, запланировав и закомментировав строку, в которой я выполняю setExactAndAllowWhileIdle()
, а затем сравнив ее вывод с выводом "adb shell dumpsys alarm".
Я оставил программу работающей в течение 24 часов. После проверки моих журналов я увидел, что будильник работал в течение 2 часов, и когда он перестал работать, он был активирован, но больше не срабатывал ...
И мое приложение не убивается, потому что, несмотря на то, что этот сигнал перестает срабатывать, другой все еще продолжает работать, и я использую точно такой же механизм, как и код ниже.
Это класс MyAlarmManager:
class MyAlarmManager(private val ctx: Context) {
private val TAG = "MyAlarmManager"
val CUSTOM_INTENT = "com.test.intent.action.ALARM"
private val mAlarmManager = ctx.getSystemService(Context.ALARM_SERVICE) as AlarmManager
fun setAlarm(frameType: FrameType, delayInMinutes: Int, force: Boolean) {
LogsHandler.writeLogs(TAG, "setAlarm()")
checkAlarmsToCancel(frameType)
val triggerAt = getTriggerTime(delayInMinutes, force)
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt.timeInMillis, getPendingIntent(frameType))
LogsHandler.writeLogs(TAG, "Se ha programado la alarma de tipo $frameType a la hora: ${Date(triggerAt.timeInMillis)}")
if(isAlarmActive(frameType))
LogsHandler.writeLogs(TAG, "La alarma está activada")
else
LogsHandler.writeLogs(TAG, "La alarma NO está activada")
}
private fun getAlarmIntent(frameType: FrameType) :Intent{
return when(frameType){
FrameType.PRESENCE -> Intent(ctx, StartPresenceReportService::class.java)
FrameType.STEPS -> Intent(ctx, StartStepsCountReportService::class.java)
FrameType.LOCATION -> Intent(ctx, StartLocationDeliveryService::class.java)
}
}
private fun getPendingIntent(frameType: FrameType): PendingIntent {
val alarmIntent = getAlarmIntent(frameType)
alarmIntent.action = CUSTOM_INTENT
return PendingIntent.getBroadcast(ctx, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT)
}
}
Это мой BroadcastReceiver:
class StartLocationDeliveryService: BroadcastReceiver() {
private var TAG = "StartLocationDeliveryService"
override fun onReceive(context: Context, intent: Intent) {
//Irrelevant code
LocationDeliveryService().executeWork(context, intent)
}
}
Это LocationDeliveryService:
class LocationDeliveryService {
private var TAG = "LocationDeliveryService"
fun executeWork(context: Context, intent: Intent) {
//Business logical operations
MyAlarmManager(context).setAlarm(FrameType.LOCATION, minutesBetweenLocationDeliveryMsgs, false)
}
}