15

I have implemented JobIntentService to do some background task which works fine on older Android devices (pre Android O). I see the intent is handled immediately but on Android O device there is some delay before JobIntentService.onHandleWork()is executed. I understand that intents are handled serially but I see the delay even if there are no intents being processed in the queue. Is it because job scheduling is handled internally in Android O?

Here, Android document says

"When running as a pre-O service, the act of enqueueing work will generally start the service immediately, regardless of whether the device is dozing or in other conditions. When running as a Job, it will be subject to standard JobScheduler policies for a Job with a setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs."

Is the above statement valid even if my app is targeted to API 25 but running on OS Android O? If so, is there any workaround to start the service/job immediately on Android O?

My current implementation:

public class MySampleService extends JobIntentService {

    private static final int JOB_ID = 1000;

    public MySampleService() {

    }

    /**
     * Convenience method for enqueuing work in to this service.
     */
    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, MySampleService.class, JOB_ID, work);
    }

    /**
     * Interpret the incoming intent actions and handle it appropriately.
     * @param workIntent
     */
    @Override
    protected void onHandleWork(@NonNull Intent workIntent) {
        if(workIntent==null || workIntent.getAction() == null){
            return;
        }
        /* This gets printed immediately on pre Android O devices but not otherwise*/
        System.out.println("Intent Handled");
    }
}
Prudhvi
  • 2,276
  • 7
  • 34
  • 54

2 Answers2

11

Is the above statement valid even if my app is targeted to API 25 but running on OS Android O?

Yes. JobIntentService behavior — using JobScheduler or not — is dictated by the version of Android that you are running on. Your targetSdkVersion has no impact.

If so, is there any workaround to start the service/job immediately on Android O?

Don't use JobIntentService. Use a regular foreground service. By definition, JobScheduler can schedule jobs as it sees fit, and there is no guarantee that it will execute a job immediately.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks CommonsWare. If I were to launch a background task, during `onPause` (I want to send a bunch of data over the network during app quit), should I use `JobIntentService` or just start a regular `IntentService`? – Cheok Yan Cheng Feb 08 '18 at 15:07
  • @CheokYanCheng: Well, quite possibly neither. Unless this work is likely to take several seconds, just do something else (RxJava, an `Executor`, etc.). And, for "app quit", use `ProcessLifecycleOwner`, not `onPause()`, as that gets called a lot, particularly in multi-window scenarios. If the work may exceed several seconds, the choice between `IntentService` and `JobIntentService` comes down to immediacy, how long the work might take, and whether you can show a `Notification` while that work is going on. Either approach could be correct; it depends on the situation. – CommonsWare Feb 08 '18 at 15:11
  • Yes. The job will take more than several seconds. Not sure if I use `IntentService`, will the OS kill it? `ProcessLifecycleOwner` is something new to me. My plan is check for `isFinishing` in `onPause`. – Cheok Yan Cheng Feb 08 '18 at 15:48
  • @CheokYanCheng: "Not sure if I use IntentService, will the OS kill it?" -- on Android 8.0+, if it will run for more than a minute, and it is not a foreground service, then yes. "My plan is check for isFinishing in onPause" -- that works for an individual activity, not for the entire UI of a multi-activity app. – CommonsWare Feb 08 '18 at 16:24
  • If you fire up an IntentService while your app is in the background, Android 8+ will kill it too...has to be a Job unless you want a foreground notification indicator. You're supposed to get 4sec before your foreground service has to call startForegroundService, but I found that 4sec window was less. Best to use a Job... – kenyee Apr 06 '18 at 18:29
  • @CommonsWare Can I invoke JobIntentService when the app is not running at all upon receiving some broadcast with action like 'android.intent.action.MY_PACKAGE_REPLACED' on Android 8.0+? – Namrata Bagerwal Apr 19 '18 at 04:50
  • 1
    @NamrataBagerwal: Well, once you receive the broadcast, your `BroadcastReceiver` can enqueue some work for a `JobIntentService`. By definition, once you receive the broadcast, your app is running. – CommonsWare Apr 19 '18 at 09:36
  • @CommonsWare, I'm thinking to switch to foreground service over JobIntentService as you suggested. I've couple of database queries in the JobIntentService at the moment. As my requirement is timely reminders, It's difficult to rely on JobIntentService for Android 8+. But the documentation says to limit the use of foreground service (Caution) - https://developer.android.com/guide/components/services#Foreground. What should I do? Thanks in advance. – Harsh4789 Oct 18 '18 at 11:00
  • @Harsh4789: If your work is time-sensitive, you have little choice but to use things like a foreground service. – CommonsWare Oct 18 '18 at 11:46
  • @CommonsWare, I can understand. Can Google have any issue with the use of foreground service in my case? The reason I am asking is that caution, mentioned to the documentation, fears me a lot. – Harsh4789 Oct 18 '18 at 12:41
  • @Harsh4789: I can't answer that, sorry. – CommonsWare Oct 18 '18 at 21:37
  • @CommonsWare, No worries. Final question. I have been testing time to execute the JobIntentService task on 3 devices, it's 110 ms maximum, usually it is around 70 ms, I have also tested on worst phone. Should I take the risk of doing this work to the broadcast receiver itself only for oreo, rather than starting a JobIntentService. Documentation says we have 5 seconds to execute the tasks. Is there any possibility of ANR in my case? Can the things go wrong in my case in any way? – Harsh4789 Oct 19 '18 at 13:44
  • @Harsh4789: "Is there any possibility of ANR in my case? Can the things go wrong in my case in any way?" -- I can't really answer that, as I do not know what the work is and what might slow it down or block it. If you have some ability to add a timeout, you could set a timeout well under the 5-second limit to try to avoid the ANR. I'm guessing that your plan is to use `goAsync()`, which I know that people use, but I find its documentation to be lacking, so I have trust issues. :-) – CommonsWare Oct 19 '18 at 20:50
  • Hey CommonsWare, do you think there are scenarios where it makes sense to run an `IntentService` as a `foreground service` rather than a `JobIntentService`? I guess you would do this if you want to start the work immediately? – Florian Walther Nov 11 '18 at 18:38
  • 1
    @FlorianWalther: Yes. That is what I suggested in the latter half of my answer. The price that you have to pay is the `Notification`, and in some cases, the user might value that `Notification`. – CommonsWare Nov 11 '18 at 18:56
  • Any idea how long `JobIntentService` can take before it runs in extreme cases? In the opening post, it was ~1min. Do you have any other experiences with that? – Florian Walther Nov 11 '18 at 21:15
  • @FlorianWalther: I have not done that much experimentation on it, sorry. – CommonsWare Nov 11 '18 at 21:28
  • I am trying to figure it out by experimenting, but I don't know how I would call `enqueue` while the device is in doze. Is that even possible without waking it up? The docs state that the job will not be executed while the device is in doze, but how would I then trigger the `enqueue` call? Because right now my job always gets executed immediately. – Florian Walther Nov 12 '18 at 10:08
  • Even if I enqueue multiple loads of work for several minutes, unplug the phone and turn the screen off, all jobs get executed – Florian Walther Nov 12 '18 at 10:53
  • @FlorianWalther: You might want to ask a separate Stack Overflow question regarding this. – CommonsWare Nov 12 '18 at 12:34
  • Thank you, maybe we can talk about it here https://stackoverflow.com/questions/53248528/intentservice-startforeground-vs-jobintentservice Because right now I can't really find examples where the job is deferred – Florian Walther Nov 13 '18 at 13:50
  • Here delays for up to 24hours are mentioned as example values for possible delays with the app standby buckets: https://developer.android.com/topic/performance/power/power-details.html – xuiqzy Jan 12 '20 at 21:30
  • @CommonsWare i want to know about intentservice...does the intentservice gets stopped/kill when application kills ???? please reply? – Wini Sep 28 '20 at 10:48
  • @Wini: `IntentService` is deprecated, and it is not designed to run for an extended period of time in the first place. Whether any sort of `Service` is affected by "application kills" depends a lot on what you mean by "application kills". If you mean swiping the app's task off of the overview screen, then what happens to a `Service` depends on device manufacturer, but there is a good chance that your `Service` process will be terminated. – CommonsWare Sep 28 '20 at 11:08
0

In case if anyone is looking for some data:

Test Device : Nokia 6.1+
OS: Android 10

I have background location receiver scheduled for every 1 min location updates and from receiver I am starting JobIntentService. In below logs you can see that Receiver got called multiple times and job also enqueued multiple times from Receiver. But onHandleIntent of JobIntentService get's called after almost 1/2 hours. Although this delay can vary in multiple scenarios.

1594846546292,2020.07.16 02:25:46.292,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594846760376,2020.07.16 02:29:20.376,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594847109044,2020.07.16 02:35:09.044,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594847509297,2020.07.16 02:41:49.297,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594847721898,2020.07.16 02:45:21.898,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594848071300,2020.07.16 02:51:11.300,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594848471389,2020.07.16 02:57:51.389,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594848685257,2020.07.16 03:01:25.257,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594849033283,2020.07.16 03:07:13.283,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594849433274,2020.07.16 03:13:53.274,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594849646987,2020.07.16 03:17:26.987,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594849995278,2020.07.16 03:23:15.278,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594850395353,2020.07.16 03:29:55.353,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594850609101,2020.07.16 03:33:29.101,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594850957287,2020.07.16 03:39:17.287,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851521664,2020.07.16 03:48:41.664,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521668,2020.07.16 03:48:41.668,DEBUG,PRETTY_LOGGER,New Location = 19.2298493,72.824765
1594851521673,2020.07.16 03:48:41.673,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521675,2020.07.16 03:48:41.675,DEBUG,PRETTY_LOGGER,New Location = 19.2298482,72.8247637
1594851521677,2020.07.16 03:48:41.677,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521679,2020.07.16 03:48:41.679,DEBUG,PRETTY_LOGGER,New Location = 19.2298484,72.8247622
1594851521681,2020.07.16 03:48:41.681,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521682,2020.07.16 03:48:41.682,DEBUG,PRETTY_LOGGER,New Location = 19.2298492,72.8247653
1594851521686,2020.07.16 03:48:41.686,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521687,2020.07.16 03:48:41.687,DEBUG,PRETTY_LOGGER,New Location = 19.229849,72.8247665
1594851521690,2020.07.16 03:48:41.690,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521691,2020.07.16 03:48:41.691,DEBUG,PRETTY_LOGGER,New Location = 19.229849,72.8247664
1594851521694,2020.07.16 03:48:41.694,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521695,2020.07.16 03:48:41.695,DEBUG,PRETTY_LOGGER,New Location = 19.229849,72.8247664
1594851521698,2020.07.16 03:48:41.698,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521699,2020.07.16 03:48:41.699,DEBUG,PRETTY_LOGGER,New Location = 19.2298461,72.8247634
1594851521701,2020.07.16 03:48:41.701,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521702,2020.07.16 03:48:41.702,DEBUG,PRETTY_LOGGER,New Location = 19.2298493,72.824765
1594851521705,2020.07.16 03:48:41.705,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521706,2020.07.16 03:48:41.706,DEBUG,PRETTY_LOGGER,New Location = 19.2298492,72.8247653
1594851521709,2020.07.16 03:48:41.709,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521710,2020.07.16 03:48:41.710,DEBUG,PRETTY_LOGGER,New Location = 19.2298491,72.8247648
1594851521713,2020.07.16 03:48:41.713,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521715,2020.07.16 03:48:41.715,DEBUG,PRETTY_LOGGER,New Location = 19.2298482,72.824763
1594851521717,2020.07.16 03:48:41.717,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521718,2020.07.16 03:48:41.718,DEBUG,PRETTY_LOGGER,New Location = 19.2298489,72.8247663
1594851521721,2020.07.16 03:48:41.721,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521722,2020.07.16 03:48:41.722,DEBUG,PRETTY_LOGGER,New Location = 19.229849,72.824766
1594851521725,2020.07.16 03:48:41.725,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594851521727,2020.07.16 03:48:41.727,DEBUG,PRETTY_LOGGER,New Location = 19.2298492,72.824766
1594851521743,2020.07.16 03:48:41.743,DEBUG,PRETTY_LOGGER,destroying location update service..
1594851568410,2020.07.16 03:49:28.410,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851568423,2020.07.16 03:49:28.423,DEBUG,PRETTY_LOGGER,Location Result is null
1594851569552,2020.07.16 03:49:29.552,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851569582,2020.07.16 03:49:29.582,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851569584,2020.07.16 03:49:29.584,DEBUG,PRETTY_LOGGER,Location Result is null
1594851842731,2020.07.16 03:54:02.731,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851884757,2020.07.16 03:54:44.757,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594851966580,2020.07.16 03:56:06.580,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594852014859,2020.07.16 03:56:54.859,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594852099687,2020.07.16 03:58:19.687,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594852430624,2020.07.16 04:03:50.624,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430626,2020.07.16 04:03:50.626,DEBUG,PRETTY_LOGGER,New Location = 19.2298507,72.8247664
1594852430632,2020.07.16 04:03:50.632,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430636,2020.07.16 04:03:50.636,DEBUG,PRETTY_LOGGER,New Location = 19.2298511,72.8247665
1594852430639,2020.07.16 04:03:50.639,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430640,2020.07.16 04:03:50.640,DEBUG,PRETTY_LOGGER,New Location = 19.2298491,72.8247654
1594852430643,2020.07.16 04:03:50.643,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430645,2020.07.16 04:03:50.645,DEBUG,PRETTY_LOGGER,New Location = 19.229852,72.8247669
1594852430648,2020.07.16 04:03:50.648,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430650,2020.07.16 04:03:50.650,DEBUG,PRETTY_LOGGER,New Location = 19.229852,72.8247669
1594852430653,2020.07.16 04:03:50.653,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594852430655,2020.07.16 04:03:50.655,DEBUG,PRETTY_LOGGER,New Location = 19.2298517,72.8247667
1594852430664,2020.07.16 04:03:50.664,DEBUG,PRETTY_LOGGER,destroying location update service..
1594852532540,2020.07.16 04:05:32.540,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594852929377,2020.07.16 04:12:09.377,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853035393,2020.07.16 04:13:55.393,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853097587,2020.07.16 04:14:57.587,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853518088,2020.07.16 04:21:58.088,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853580673,2020.07.16 04:23:00.673,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853641964,2020.07.16 04:24:01.964,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853843544,2020.07.16 04:27:23.544,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853904843,2020.07.16 04:28:24.843,DEBUG,PRETTY_LOGGER,Location updates receiver called
1594853947748,2020.07.16 04:29:07.748,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594853947777,2020.07.16 04:29:07.777,DEBUG,PRETTY_LOGGER,New Location = 19.2298533,72.8247706
1594853947781,2020.07.16 04:29:07.781,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594853947783,2020.07.16 04:29:07.783,DEBUG,PRETTY_LOGGER,New Location = 19.229852,72.8247669
1594853947786,2020.07.16 04:29:07.786,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594853947787,2020.07.16 04:29:07.787,DEBUG,PRETTY_LOGGER,New Location = 19.2298493,72.8247656
1594853947789,2020.07.16 04:29:07.789,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
1594853947791,2020.07.16 04:29:07.791,DEBUG,PRETTY_LOGGER,New Location = 19.2298494,72.8247659
1594853947793,2020.07.16 04:29:07.793,DEBUG,PRETTY_LOGGER,Handling work in CTLocationUpdateService...
Piyush Kukadiya
  • 1,880
  • 16
  • 26