Edit: Clarified the question based on CommonsWare's answer
We're scheduling an an alarm via AlarmManager to trigger every 60 seconds. When our application is killed our alarms seem to no longer execute. Is there a way to make these alarms persist even when the application is killed manually or by the system?
This is a problem for us because we have a widget application that displays the time. This means we need to update the time every minute. To get around the 30 minute update limit on the onUpdate method of AppWidgetProvider we use AlarmManager. It usually works pretty well, but some users have reported the time going out of sync. After talking to several of them, my suspicion is that our application is being killed manually via a task killer app or Android is itself is killing our app.
Any other alternate solutions to the root problem (keeping the time in sync in a widget) welcome as well.
Here is the code we execute to schedule our alarm:
Intent intent = new Intent(UPDATE_TIME); PendingIntent pIntent = PendingIntent.getBroadcast(ctx, 0 /* no requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT ); // get alarm params Date d = new Date(); long timeTilMinuteChange = 60*1000-d.getSeconds()*1000; long startTime = System.currentTimeMillis() + + timeTilMinuteChange; AlarmManager am = (AlarmManager) ctx.getSystemService(Context. am.cancel(pIntent); am.set(AlarmManager.RTC, System.currentTimeMillis(), pIntent); am.setRepeating(AlarmManager.RTC, startTime, 60000, pIntent);
IntentService + WakefulBroadcastReceiver + AlarmManager are deprecated with API 26 (Android 8.0 Oreo).
How does an application get access to the AlarmManager? Use the AlarmManager() constructor to create an instance of the AlarmManager. Use the AlarmManager. newInstance() method to retrieve the singleton instance of the AlarmManager.
This example demonstrates how do I implement alarm manager in android. Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml.
Open your phone's Clock app . At the bottom, tap Alarm. On the alarm you want, tap the Down arrow . Cancel: To cancel an alarm scheduled to go off in the next 2 hours, tap Dismiss.
Whenever our application is killed, the AlarmManager is also killed.
AlarmManager
is not killed. Your alarm, however, is canceled. If the user force-stops or task-kills you, your alarms are unscheduled. On Android 3.1+, if the user force-stops you, nothing of your code will run again until the user manually launches one of your activities.
After talking to several of them, my suspicion is that our application is being killed manually via a task killer app or Android is itself is killing our app.
Ideally, your app should not be written in such a way that Android would have any cause to get rid of you. For something like what you describe, you should either using a getBroadcast()
PendingIntent
pointing to a manifest-registered BroadcastReceiver
, or you should be using a getService()
PendingIntent
pointing to an IntentService
. In either case, your code will run briefly, and then your process will be eligible for reclamation by Android without issue should the need arise.
Task killers, whether manual or automatic, seem a far more likely culprit of alarms being canceled, IMHO.
About the alarm manager in the Docs - the explanation is somewhat confusing and I honestly still don't get it fully. I have this bit of code for the widget part that solved the problem in my case.
package com.test.mytestwidget; import java.util.Calendar; import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; public class MyWidgetProvider extends AppWidgetProvider { private PendingIntent service = null; public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); final Calendar TIME = Calendar.getInstance(); TIME.set(Calendar.MINUTE, 0); TIME.set(Calendar.SECOND, 0); TIME.set(Calendar.MILLISECOND, 0); final Intent i = new Intent(context, UpdateWidgetService.class); if (service == null) { service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); } m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 30000, service); } @Override public void onDisabled(Context context) { final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); m.cancel(service); super.onDisabled(context); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With