9

Sometimes in my apps I need to do something in the background repeatedly (every X hours).

Up to API 25 i use:

  • AlarmManager with setInexactRepeating (to respect battery)
  • WakefulBroadcastReceiver to have enough times to do all works
  • IntentService to do all in background thread

On API 26 all of this are deprecated or limited and are suggested to use JobScheduler with JobService instead.

The problem is that JobService run in main thread.

I think to use AsyncTask inside JobService and call JobService.jobFinished inside onPostExecute

this is the correct way to do this?

Alessandro Scarozza
  • 4,273
  • 6
  • 31
  • 39

2 Answers2

7

You can use JobIntentService of support library 26 which has the exact workflow of IntentService. For pre Oreo devices, JobIntentService will use old IntentService. JobIntentService class relies on JobScheduler API of android.

For more, https://developer.android.com/reference/android/support/v4/app/JobIntentService.html

Athul Antony
  • 220
  • 2
  • 8
6

On API 26 all of this are deprecated or limited

AlarmManager did not change in Android 8.0, IIRC. IntentService did not change in Android 8.0 either. However, you would need to make the IntentService be a foreground service and use a getForegroundService() PendingIntent.

The problem is that JobIntentService run in main thread.

onHandleWork() is called on a background thread, both for Android 8.0+ and pre-8.0 devices. I used this sample app of mine, adding logging statements to log the current thread ID inside enqueueWork() (called on the main application thread) and onHandleWork(). They are different thread IDs, and hence they are different threads.

this is the correct way to do this?

No, just do your work in onHandleWork().

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • from IntentService doc: "Note: IntentService is subject to all the background execution limits imposed with Android 8.0 (API level 26). In most cases, you are better off using JobIntentService, which uses jobs instead of services when running on Android 8.0 or higher." also i need to run service each X hours (not exactly) even if app is closed, so i cant run enqueueWork directly – Alessandro Scarozza Oct 10 '17 at 18:03
  • @Xan: "from IntentService doc" -- which is why I pointed out that you would need to make it a foreground service. "also i need to run service each X hours (not exactly) even if app is closed" -- then use `JobScheduler` directly, forking a regular thread (not an `AsyncTask`) from `onStartJob()`. – CommonsWare Oct 10 '17 at 18:06
  • sorry i confused JobIntentService with JobService in question. so we can use JobIntentService as IntentService and JobService as Service ? can i use JobIntentService inside JobScheduler ? (i will edit question) – Alessandro Scarozza Oct 10 '17 at 18:10
  • @Xan: You use a `JobService` with `JobScheduler`. You use `JobIntentService` as a replacement for `IntentService` (e.g., with `AlarmManager`, using a `BroadcastReceiver` `PendingIntent`, where the receiver calls `enqueueWork()` on the `JobIntentService`). – CommonsWare Oct 10 '17 at 18:29
  • so using AlarmManager, BroadcastReceiver and JobIntentService there is no problem with API 26 ? (about background limitation) – Alessandro Scarozza Oct 10 '17 at 18:34
  • @Xan: It's more that you get ~10 minutes instead of ~1 minute. If you have work that might exceed 10 minutes, use a foreground `IntentService`. – CommonsWare Oct 10 '17 at 18:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/156386/discussion-between-xan-and-commonsware). – Alessandro Scarozza Oct 10 '17 at 18:41
  • @CommonsWare PendingIntent.getForegroundService requires API 26 , is there any why to get this on PRE 26 ? Support library? – redochka Jan 14 '19 at 10:39
  • @redochka: On previous versions, you would just use `PendingIntent.getService()`. – CommonsWare Jan 14 '19 at 11:49
  • @Xan AlarmManager not depreceted but only "Note: Beginning with API 19 (Build.VERSION_CODES.KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, android.app.PendingIntent) and setExact(int, long, android.app.PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested." – Fortran Dec 15 '20 at 12:55
  • @CommonsWare I used a JobIntentService to fire Notifications to the user when exact Alarms were triggered. What do you suggest I use now that JobIntentService is deprecated? WorkManager? – AJW Oct 17 '21 at 19:43
  • @AJW: That depends on whether there is other work. If all you are doing is just displaying the `Notification`, with no I/O, then a regular short-lived background `Service` or even a `BroadcastReceiver` might suffice -- basically, whatever is directly responding to the `AlarmManager` event. If, however, you need to do disk or network I/O as part of displaying the `Notification`, then `WorkManager` probably is a good idea. – CommonsWare Oct 17 '21 at 19:46
  • @CommonsWare an AlarmManager gets triggered when an exact calendar due date is hit, which then runs a BroadcastReceiver to launch the JobIntentService. And the JobIntentService fires a simple Notification message to the user. So pretty simple and no network I/O...so would recommend to just use Service? – AJW Oct 17 '21 at 20:01
  • @AJW: I would just do it all in the `BroadcastReceiver`. Raising a `Notification` should be very cheap in your case; I do not know what value you got from the `JobIntentService`. – CommonsWare Oct 17 '21 at 20:02
  • Ok. I set up the JobIntentService so the Notification firing and delivery to the user was on a worker thread because I thought BroadcastReceiver is always run on the UI thread. Are you saying that the Notification firing and delivery is such a small hit to the main thread that it is not necessary to put on a worker thread for background processing? – AJW Oct 17 '21 at 20:08
  • @AJW: "Are you saying that the Notification firing and delivery is such a small hit to the main thread that it is not necessary to put on a worker thread for background processing?" -- correct. We need worker threads for I/O or computationally-intensive work. Raising a `Notification` should not qualify for either of those. – CommonsWare Oct 17 '21 at 20:30
  • @CommonsWare Very good...you are a gentleman and a scholar. Cheers. – AJW Oct 17 '21 at 20:31
  • CommonsWare I forgot to ask you about this use case: would resetting say 200 calendar date alarms in a for loop, based on a device reboot event BOOT_COMPLETED be computationally-intensive? If yes, then have BroadcastReceiver launch WorkManager for execution in a worker thread? – AJW Oct 19 '21 at 02:42
  • @AJW: "would resetting say 200 calendar date alarms in a for loop... be computationally-intensive?" -- I am not certain what it means to reset a calendar date alarm. You could use logging to determine how long it takes. – CommonsWare Oct 19 '21 at 11:04