1

I have some existing code that spawns a service intent which does a bunch of stuff in the background. This code does work...

Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startService(serviceIntent);

My question is: how to change this to use the AlarmManager.setInexactRepeating(...) methods?

I have changed the above code to this:

Intent serviceIntent = new Intent(context, APMService.class);
serviceIntent.putExtra("STARTED_BY", starter);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

//Set up recurring alarm that restarts our service if
// it crashes or if it gets killed by the Android OS
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(context, 0, serviceIntent, 0);
//am.cancel(pi);

am.setInexactRepeating(
        AlarmManager.ELAPSED_REALTIME_WAKEUP    //wake up the phone if it's asleep
        , cal.getTimeInMillis()
        , 10000
        , pi);

And I have added these permissions to AndroidManifest.xml...

<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<uses-permission android:name="com.android.alarm.permission.WAKE_LOCK"/>

My understanding is that this is supposed to start the service immediately and then try to restart it again every 10 seconds. But this code isn't working properly.

Using this new code, the service never starts at all and I cannot see why not. To complicate matters the debugger never seems to attach to the app in time to see what's going on.

Can anyone see what I'm doing wrong?

2 Answers2

1

Put AlarmManager code under onDestroy() function of service to schedule start of service as below:

    @Override
        public void onDestroy() {

    /**
             * Flag to restart service if killed.
             * This flag specify the time which is ued by
             * alarm manager to fire action.
             */
            final int TIME_TO_INVOKE = 5 * 1000; // try to re-start service in 5 seconds.

            // get alarm manager
            AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Intent intent = new Intent(context, AutoStartServiceReceiver.class);
            PendingIntent pendingIntent = PendingIntent
                .getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

            // set repeating alarm.
            alarms.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() +
                    TIME_TO_INVOKE, TIME_TO_INVOKE, pendingIntent);

    }

And handle starting of your service in AutoStartServiceReceiver as below:

public class AutoStartServiceReceiver extends BroadcastReceiver {

    private static final String TAG = AutoStartServiceReceiver.class.getSimpleName();

    @Override
    public void onReceive(Context context, Intent intent) {
        // check broadcast action whether action was
        // boot completed or it was alarm action.
        if (intent.getAction().equals(AppConstants.ACTION_ALARM_INTENT)) {
            context.startActivity(new Intent(context, YourActivity.class));
            // handle service restart event
            LockerServiceHelper.handleServiceRestart(context);
        }
    }
}

Kindly note that, your service will not restart if you stop it manually from settings-apps-running apps-your app.

Geeky Singh
  • 1,003
  • 9
  • 20
  • 1
    Where can I find **AppConstants.ACTION_ALARM_INTENT**? I cannot find it in this scope, is there an import I need? Also, does this require a new permission? –  Jan 14 '16 at 12:56
  • 1
    Keep in mind that `onDestroy` is not guaranteed to be called by the system. – InTwoMinds Jan 14 '16 at 13:05
  • This was helpful, thanks Gagan. I took @InTwoMinds' advice and it made the code work, but then I moved it all into my onDestroy as you suggested. Working nicely now. Cheers. –  Jan 14 '16 at 14:02
  • @GaganSingh, your code didn't solve the problem, nor would it compile (see comment above). But it was a good suggestion for other reasons. Thanks for your input. –  Jan 15 '16 at 07:47
  • AppConstants.ACTION_ALARM_INTENT is a constant declared in my AppConstants class. Instead, you can declare and use your own. – Geeky Singh Jan 15 '16 at 07:49
0

Your service is not starting because of AlarmManager.ELAPSED_REALTIME_WAKEUP, while it should be using AlarmManager.RTC_WAKEUP

If you want to run every 10s keep in mind that above API 21 alarm intervals below 60s are rounded up to 60s.

Also, consider using WakefulIntentService https://github.com/commonsguy/cwac-wakeful

InTwoMinds
  • 655
  • 4
  • 9
  • Yes, you were right, that was what was preventing my code from working. I also took @Gagan Singh's advice to move the code into the onDestroy of the Service. This is now working nicely. Thanks to both of you. –  Jan 14 '16 at 13:59