Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a persistent AlarmManager

Tags:

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); 
like image 362
christoff Avatar asked Feb 01 '12 19:02

christoff


People also ask

Is AlarmManager deprecated?

IntentService + WakefulBroadcastReceiver + AlarmManager are deprecated with API 26 (Android 8.0 Oreo).

How does an application get access to the AlarmManager?

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.

How do I set alarm manager on android?

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.

How do I stop my android phone from repeating an alarm?

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.


2 Answers

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.

like image 143
CommonsWare Avatar answered Dec 11 '22 20:12

CommonsWare


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);      }        } 
like image 36
Scalarr Avatar answered Dec 11 '22 21:12

Scalarr