Question

I have a problem with AlarmManager, I set the code for scheduling a repeating alarm and after I run the application, the alarm runs fine. Even if I click on Home button (and the application is paused), the alarm still runs on its interval.

The problem is if I open the Task Manager and force close the application, then the alarm stops from running.

Is this a normal behavior, is there any way to avoid this and keep the alarm running after closing the application?

The code is below - the method is called by the ApplicationContext class, onCreate().

 private void scheduleAlarm() {
  if (alarmScheduled == true) { return; } // we only need to schedule once.

  int alarmInterval = Def.pref(getApplicationContext()).getInt("alarmInterval", 30);

  final Intent intent = new Intent(getApplicationContext(), CollectorAlarmReceiver.class);
  final PendingIntent pending = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);

  AlarmManager alarmMgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

  alarmMgr.cancel(pending); // cancel others.

  alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000,
    alarmInterval*1000, pending);

  Def.log(TAG,"scheduleAlarm(): alarm scheduled, interval: "+alarmInterval+" seconds");
  alarmScheduled = true;
 }

Receiver code:

public void onReceive(Context context, Intent intent) {
    Log.i(TAG, "CollectorAlarmReceiver invoked, starting CollectorService in background");

    context.startService(new Intent(context, CollectorService.class));

    Intent collectorService = new Intent(context,CollectorService.class);
    collectorService.putExtra("action", CollectorService.ACTION_BACKGROUND_REQUEST_MESSAGES);

    context.sendBroadcast(collectorService);
}

Thanks!

Was it helpful?

Solution

This is normal behaviour. If the user voluntarily force stop the applicaiton, then it should be stopped. Else, you are creating a virus like application.

If you really want, you could write another service which monitors if your other service is running and runs the service if the one is not running. But this will be another application and (you hope) the user wont kill this app using task manager.

Personally, I wouldn't worry. If the user stopped it, they wanted to stop it. Don't annoy the user.

OTHER TIPS

I believe @GSree is wrong. There's a simple way to achieve this. Just use a custom action. Here's how:

First, define a custom action name, such as:

public static final String MY_ACTION = "com.sample.myaction"

Then create a BroadcastReceiver:

public class MyAlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(MY_ACTION)) {
            // Do something here
        }
    }    
}

Register the receiver on your AndroidManifest.xml:

<receiver android:name="com.sample.MyAlarmReceiver">
    <intent-filter>
        <action android:name="com.sample.myaction"/>
    </intent-filter>
</receiver>

Then, to setup the alarm, use the following PendingIntent:

Intent i = new Intent(MY_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

There may be other ways to do it, but I tried this solution and the BroadcastReceiver gets called even if I force-quit my app from the shell.

Notice how this solution does not require you to create a service.

That's a normal behavoiur ! The alarm will stop working when your app goes to onDestroy().

I've done this a few times, but wonder why ya'll are assigning a requestCode of 0; I'd think that giving your alarm a unique number would help a lot.

Forcing your application to close is not the correct way to close an app and may give you incorrect behavior.

This question might also be of some help.

I have been able to do exactly what you need. Even if you stop the application through the running tab in the application manager tool, the service restarts itself. The only way to kill it is throught the force stop button next to the unistall option in application manager. Basically you call the Service directly. Here is My Code:

public class TestService extends Service {

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "Ejecutando Servicio ...", Toast.LENGTH_SHORT).show();
    return Service.START_NOT_STICKY;    
    }

@Override
    public void onCreate() {
      super.onCreate();
      Toast.makeText(this, "Iniciando Servicio ...", Toast.LENGTH_SHORT).show();
}

    @Override
    public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Deteniendo Servicio ...", Toast.LENGTH_SHORT).show();
}   

On client activity write the following code:

            Calendar cal = Calendar.getInstance();
        Intent intent = new Intent(this,TestService.class);
        PendingIntent pIntent = PendingIntent.getService(this.getApplicationContext(), 0, intent, 0);
        alarm=  (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarm.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), 3*1000, pIntent);

And declare the service in manifest:

        <service
      android:name="TestService"
      android:icon="@drawable/ic_launcher"
      android:label="TestService"
      >
    </service>         

Add

<receiver android:name=".AlarmReceiver" android:process=":remote" />

in manifest file. The alarm will work even if app is killed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top