Reputation: 9548
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();
}
}
Boot Complete
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).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
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
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