Zbarcea Christian
Zbarcea Christian

Reputation: 9548

Sometimes alarms doesn't get triggered using AlarmManager

I have a reminder app which notifies the user for a specific task. Everything is working as expected, but sometimes the alarm doesn't get triggered. This issue was reported by nearly 100 users. I suspect that when the devices are in sleep mode, the alarms are not triggered. I am facing this issue for nearly 1 year and I haven't found any solution yet.

This is how the alarms are getting scheduled:

public void schedule(Context context, long nextTrigger, Intent intent) {
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQ_CODE_ALARM, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    int ALARM_TYPE = AlarmManager.RTC_WAKEUP;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(ALARM_TYPE, nextTrigger, pendingIntent);
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        alarmManager.setExact(ALARM_TYPE, nextTrigger, pendingIntent);
    }
    else {
        alarmManager.set(ALARM_TYPE, nextTrigger, pendingIntent);
    }
}

This is the broadcast receiver from pending intent:

public class ReminderAlarm extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        PowerManager.WakeLock wl = null;
        if (pm != null) {
            wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, APP_NAME);
            if (wl != null)
                wl.acquire(10000L);
        }

        Log.log("Reminder alarm received");

        ReminderJobIntentService.enqueueWork(context, ReminderJobIntentService.class, JOB_ID_REMINDER_ALARM, intent);

        if (wl != null)
            wl.release();
    }
}

This is the Job Intent Service which is enqueued from the broadcast:

public class ReminderJobIntentService extends JobIntentService {

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        Log.log("Reminder job intent service");

        // Creates a notification on the UI
        Utils.createNotification();

        // Schedule the next task (alarm). Actually it's schedule(context, long, intent) but it calculates the next trigger. That's it
        Scheduler.getInstance().scheduleNext();
    }
}
  1. I have logs that the alarms were scheduled correctly. When the broadcast is received (when the alarm is triggered) I'm logging this as well. When there are no logs with the broadcast, it means that the alarm doesn't triggered.
  2. The alarms are scheduled at Boot Complete
  3. I have tried to reproduce this issue several times with different Android devices and versions but I can't reproduce it. I even tried to put the device in Doze Mode and Battery Unpluged, but no luck. The alarms were triggered. I left the device untouched for nearly 3 days, the alarms were triggered with a 4 minute delay (because of Android OS is batching the alarms).
  4. When a user is complaining about the reminders are not received, usually I redirect them to "Settings -> Battery -> Ignore battery optimization for app". But sometimes this doesn't fix the issue.

What have I noticed that the people who are complaining about this are using Samsung devices: S6, S7, S8 models with Android 6, 7. (Maybe because 45% of my users are using this type of device?)

Have you ever encountered this specific problem? Am I missing something? Are Samsung models killing the apps in the background? Maybe some 3rd party apps are killing the apps?

Upvotes: 3

Views: 1758

Answers (2)

Mehran Baki
Mehran Baki

Reputation: 1

Recently I faced this issue and handled it like below: Use setAlarmClock instead of setExactAndAllowWhileIdle !!!

    class AndroidAlarmScheduler(private val context: Context): AlarmScheduler {

    //ALARM MANAGER
    private val alarmManager = context.getSystemService(AlarmManager::class.java)

    //SCHEDULE THE ALARM
    override fun schedule(entity: MessageEntity) {
        //INTENT NEEDS TO SEND
        val intent = Intent(context, AlarmReceiver::class.java).apply {
            putExtra("EXTRA_MESSAGE", entity.message)
            putExtra("EXTRA_PHONE", entity.phone)
            putExtra("EXTRA_MESSAGE_ID", entity.id.toString())
        }
        //SETTING ALARM USING setAlarmClock
        //PENDING INTENT
        val pendingIntent = PendingIntent.getBroadcast(
            context,
            entity.id.hashCode(),
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
        //IN CASE THAT USER CLICKED ON ALARM ICON NOTIFICATION TO CANCEL THE ALARM
        val i2 = Intent(context, MainActivity::class.java)
        val pi2 = PendingIntent.getActivity(context, entity.id.hashCode(), i2, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
        val alarmClockInfo = AlarmClockInfo(entity.time.atZone(ZoneId.systemDefault()).toEpochSecond() * 1000, pi2)

        alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
        Log.i("LOG:","${entity.id}")
    }

    //CANCELING THE SCHEDULED ALARM
    override fun cancel(entity: MessageEntity) {
        alarmManager.cancel(
            PendingIntent.getBroadcast(
                context,
                entity.id.hashCode(),
                Intent(context, AlarmReceiver::class.java),PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        )
        Log.e("LOG:","Alarm related to ${entity.id}-Canceled")
    }
}

Upvotes: 0

Garvit Jain
Garvit Jain

Reputation: 635

I have encountered a similar problem while building an app to get daily notifications. The problem is not with the code, it's with the way Alarms are handled in Android Kitkat and above. Alarms are now optimized to minimize wakeups and battery use. So they may fire at different times or not fire at all. You can look here for more info:

AlarmManager not working properly

Upvotes: 0

Related Questions