22

I read in the docs that Context.startForegroundService() has an implicit promise that the started service will call startForeground(). However, since Android O is coming out with changes to background and foreground services, are there any other performance improvements that it has compared to using the older startService() method, or is it just best practice going forward?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Willie Chalmers III
  • 1,151
  • 1
  • 16
  • 29

2 Answers2

32

It's about neither performance improvements, nor benefits, nor best practice.

Starting from API 26, system just doesn't allow a background app to create a background service.

So, if your app is in the background (you're welcome to do the same if it's in the foreground as well), you have to to use Context.startForegroundService(Intent) instead of the former startService(Intent). The service must then call startForeground(int, Notification) within first 5 seconds after it has started, otherwise system will stop the service.

It should also be mentioned that there is information that the old way with starting a service with startService(Intent) from a background app still works on the current release of Android Oreo, but it will be fixed soon.

Hence, starting from the API 26, you want to use new Context.startForegroundService(Intent) method instead of startService(Intent) whenever you want to start a foreground service.

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
  • 1
    `there is information that old way with starting a service with startService(Intent) from a bacjground app still works` Is there a source? – Eugen Pechanec Sep 10 '17 at 08:37
  • Does it mean that I have to check whether API >= 26 and if yes, then call `startForegroundService()`, otherwise call `startService()`? – scarface May 17 '19 at 09:07
  • 1
    @scarface Yes, you have to check it, otherwise an exception would be thrown when attempting to call the `startService()` method from a background app. But I believe you couid avoid a manual code for that check if you'd use a standard Android `compat` lib. – Alexander Abakumov May 21 '19 at 21:15
  • 2
    The thing is that those 5 seconds are a very short period of time. If system is busy, a Service object that is supposed to call startForeground might not be called for more than 5 seconds, and it will occasionally (not always) crash the app. Very poor design on Google's side, and it's not clear how to fix. Any ideas? – Oleg Gryb Jun 07 '19 at 17:47
  • @OlegGryb Have you tried to find an answer to your question in Android bug tracker or maybe posted a bug there to see what the Android team could advice on this specific issue? – Alexander Abakumov Jun 07 '19 at 19:46
  • Here is a bigger discussion: https://stackoverflow.com/questions/44425584/context-startforegroundservice-did-not-then-call-service-startforeground where people were opening bugs, but Google didn't do anything to fix. There are many answers, but none really addresses the issue. I do have this problem in my app and it does crash once in a month. Publishing stack trace here won't help. – Oleg Gryb Jun 07 '19 at 19:57
  • @OlegGryb Ok, glad you've found some info regarding your issue. – Alexander Abakumov Jun 07 '19 at 22:33
  • @AlexanderAbakumov yes, I've described my solution here: https://stackoverflow.com/questions/44425584/context-startforegroundservice-did-not-then-call-service-startforeground/56534432#56534432 – Oleg Gryb Jul 17 '19 at 12:57
4

As I've explained here, startForegroundService has a serious problem that will inevitably lead to infrequent ANR's. Since this problem can't be fixed at an app level, startForegroundService should not be used. I switched to JobScheduler and JobService model to implement the same functionality.

The latter model works well so far and I didn't see app crashes in Play Store anymore. The new model is quite different though and I've spent two days re-factoring existing code based on startForegroundService, but it has definitely paid off.

Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40