Search code examples
androidservicealarmmanagerbackgroundworker

Alarm manager not starting service as expected after API 23


Recently i have upgraded my project to 26 Api level. after that alarm manager is not working for me. I don't know what's the problem but i guess the alarm is not at all working, whenever app is in background for all device above lolipop(>=M). i have gone through other questions and and have followed some suggestion like 'WakefulBroadcastReceiver',

Below is my code and flow of the same

Scenario

- setting a repeative alarm for every 15 minutes.

     Intent dil = new Intent(getApplicationContext(), LocationSyncTaskReceiver.class);
        PendingIntent dlpi = PendingIntent.getBroadcast(getApplicationContext(), 225566, dil, 0);
        AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

            lFreq = 15;

        if(Build.VERSION.SDK_INT>23)
            am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,(System.currentTimeMillis()+5 * 60 * 1000L),dlpi);
        else
            am.setRepeating(AlarmManager.RTC_WAKEUP, 5 * 60 * 1000L, lFreq * 60 * 1000L, dlpi);

- which is invoking a 'WakefulBroadcastReceiver'.

  public class LocationSyncTaskReceiver extends WakefulBroadcastReceiver {

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

@Override
public void onReceive(Context context, Intent intent) {

    WakefulIntentService.acquireStaticLock(context);
    Intent locationSync = new Intent(context, SyncLocationTracker.class);
    startWakefulService(context,locationSync);
}

}

- above code is calling 'WakefulIntentService' - SyncLocationTracker

    @Override
public void doWakefulWork(Intent intent) {
    userService = UserServiceImpl.getInstance();
    Log.d(TAG, "Data Tracker : doWakefulWork called");
    if (userService.getLoggedInUser() != null) {
        Log.d(TAG, "User is logged in so continuing sync ....");
        WakefulIntentService.acquireStaticLock(getApplicationContext());
        syncService = DataSyncServiceImpl.getInstance();
        syncService.syncLocation();
    } else {
        Log.d(TAG, "User is not logged in so discarding sync ....");
        stopSelf();
    }
    stopSelf();
}

- 'syncService.syncLocation();' is finally doing a some calculation and multiple network request


Solution

  • Resolved it using this library Evernote job scheduler library

    It uses JobScheduler, GcmNetworkManager or AlarmManager depending on your android os version.

    All features from Android Oreo are backward compatible back to Ice Cream Sandwich.

    The JobRequest.Builder class has many extra options, e.g. you can specify a required network connection, make the job periodic, pass some extras with a bundle, restore the job after a reboot or run the job at an exact time.

    Example

         int jobId = new JobRequest.Builder(DemoSyncJob.TAG)
            .setExecutionWindow(30_000L, 40_000L)
            .setBackoffCriteria(5_000L, JobRequest.BackoffPolicy.EXPONENTIAL)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(false)
            .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
            .setExtras(extras)
            .setRequirementsEnforced(true)
            .setUpdateCurrent(true)
            .build()
            .schedule();