15

My app uses this classic pattern to schedule periodic tasks:

  1. Set an exact alarm via AlarmManager (via setExactAndAllowWhileIdle(), since it has to go off even in Doze)
  2. Start an IntentService from onReceive() via WakefulBroadcastReceiver.startWakefulService()
  3. Do the work in onHandleIntent() and call WakefulBroadcastReceiver.completeWakefulIntent() when finished.

Today i updated the targetSdkVersion to 26 and faced the terrible fact that WakefulBroadcastReceiver is deprecated.

I went to read API docs immediately and found the following:

As of Android O, background check restrictions make this class no longer generally useful. (It is generally not safe to start a service from the receipt of a broadcast, because you don't have any guarantees that your app is in the foreground at this point and thus allowed to do so.) Instead, developers should use android.app.job.JobScheduler to schedule a job, and this does not require that the app hold a wake lock while doing so (the system will take care of holding a wake lock for the job).

This is kinda confusing to me, i don't really understand what is the purpose of AlarmManager.setExactAndAllowWhileIdle() without being able to keep the device awake anymore.

As i see i cannot set an exact time to run a job with JobScheduler, only conditions (such as network type or charging state) so i have no idea what to do here.

I thought of either

  • Using AlarmManager and JobScheduler together

    Set an alarm (with setExactAndAllowWhileIdle()) and start a job (via JobScheduler) immediately from onReceive(). Since JobScheduler provides a WakeLock, WakefulBroadcastReceiver is not needed.

    (does this make sense?)

or

  • Keep using WakefulBroadcastReceiver despite being deprecated.

I'd really appreciate any advice on this matter.

Maddy
  • 4,525
  • 4
  • 33
  • 53
justanoob
  • 1,797
  • 11
  • 27
  • 1
    have you find nay answer ??? – K Guru Sep 27 '17 at 14:33
  • Now it's preferred to use Jetpack's [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) instead JobScheduler directly. afaik, there's still no method for setting an exact time for Work to be dispatched, so combining `AlarmManger` and `WorkManager.OneTimeWorkRequest` as you alluded to still seems the way to get a task "probably" done at a precise time [video](https://www.youtube.com/watch?v=TCylj3i5cXI) – lasec0203 Sep 20 '20 at 20:47

2 Answers2

-1

In android-o and later you can define a repeating task without alarmmanager like this:

// schedule the start of the service "TestJobService" every 10 - 30 minutes
public static void scheduleJob(Context context) {
    ComponentName serviceComponent = new ComponentName(context, TestJobService.class);
    JobInfo.Builder builder = new JobInfo.Builder(0, serviceComponent);
    builder.setMinimumLatency(10 * 60 * 1000); // wait at least
    builder.setOverrideDeadline(30 * 60 * 1000); // maximum delay
    JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
    jobScheduler.schedule(builder.build());
}
k3b
  • 14,517
  • 7
  • 53
  • 85
-1

You can use a BroadcastReciever that is triggered by your Alarm and in that receiver call JobIntentService.enqueueWork with your service, that you'll need to convert to a JobIntentService and implement the onHandleWork method.
The solution is described here:
Issue Moving from IntentService to JobIntentService for Android O

Alex Itelman
  • 199
  • 2
  • 11