I am using AlarmManager to set 2 different repeating alarms. One alarm is fired every hour at minute 59. This alarm always works correctly. But, the other alarm, which is scheduled every 5 minutes starts working properly during 1 or 2 hours. After that time, my AlarmManager schedules the alarm but it is never fired anymore.
I am using setExactAndAllowWhileIdle()
method to schedule the alarms.
In order to check whether the alarm was scheduled and activated or not, I am using this method after calling 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
}
I tested this method by scheduling and commenting out the line where I execute setExactAndAllowWhileIdle()
and then contrasting its output with "adb shell dumpsys alarm" output.
I left the program working during 24 hours. After checking out my logs, I saw that the alarm was working during 2 hours, and when it stopped to work, it was activated but not fired anymore...
And my app doesn't get killed because despite this alarm stops being fired, the other one still contiues working and I'm following exactly same mechanism as the code below.
This is MyAlarmManager class:
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)
}
}
This is my BroadcastReceiver:
class StartLocationDeliveryService: BroadcastReceiver() {
private var TAG = "StartLocationDeliveryService"
override fun onReceive(context: Context, intent: Intent) {
//Irrelevant code
LocationDeliveryService().executeWork(context, intent)
}
}
This is LocationDeliveryService:
class LocationDeliveryService {
private var TAG = "LocationDeliveryService"
fun executeWork(context: Context, intent: Intent) {
//Business logical operations
MyAlarmManager(context).setAlarm(FrameType.LOCATION, minutesBetweenLocationDeliveryMsgs, false)
}
}