I am using Service
Class on the Android O OS.
I plan to use the Service
in the background.
The Android recommendation states that startService should use startForegroundService.
If you use startForegroundService, the Service
throws a Context.startForegroundService()
did not then call Service.startForeground()
error.
What's wrong with this?
So many answer but none worked in my case.
I have started service like this.
And in my service in onStartCommand
And don't forgot to set NOTIFICATION_ID non zero
SO everything was perfect but still crashing on 8.1 so cause was as below.
I have called stop foreground with remove notificaton but once notification removed service become background and background service can not run in android O from background. started after push received.
So magical word is
So far so any reason your service is crashing follow all above steps and enjoy.
I have a work around for this problem. I have verified this fix in my own app(300K+ DAU), which can reduce at least 95% of this kind of crash, but still cannot 100% avoid this problem.
This problem happens even when you ensure to call startForeground() just after service started as Google documented. It may be because the service creation and initialization process already cost more than 5 seconds in many scenarios, then no matter when and where you call startForeground() method, this crash is unavoidable.
My solution is to ensure that startForeground() will be executed within 5 seconds after startForegroundService() method, no matter how long your service need to be created and initialized. Here is the detailed solution.
Do not use startForegroundService at the first place, use bindService() with auto_create flag. It will wait for the service initialization. Here is the code, my sample service is MusicService:
Then here is MusicBinder implementation:
The most important part, MusicService implementation, forceForeground() method will ensure that startForeground() method is called just after startForegroundService():
If you want to run the step 1 code snippet in a pending intent, such as if you want to start a foreground service in a widget (a click on widget button) without opening your app, you can wrap the code snippet in a broadcast receiver, and fire a broadcast event instead of start service command.
That is all. Hope it helps. Good luck.
Make sure that all code paths calls startForeground method , for example the code may generate an exception on the onCreate Method of your service that prevent the startForeground from being called
https://developer.android.com/reference/android/content/Context.html#startForegroundService(android.content.Intent)
make sure you call the
Service.startForeground(int, android.app.Notification)
on the onCreate() so you ensure it will be called..if you have any condition that may prevent you from doing that, then you'd better off using the normalContext.startService(Intent)
and call theService.startForeground(int, android.app.Notification)
yourself.It seems that the
Context.startForegroundService()
adds a watchdog to make sure you called theService.startForeground(int, android.app.Notification)
before it was destroyed...I have a widget which does relatively frequent updates when the device is awake and I was seeing thousands of crashes in just a few days.
The issue trigger
I even noticed the issue even on my Pixel 3 XL when I wouldn't have thought the device to have much load at all. And any and all code paths were covered with
startForeground()
. But then I realized that in many cases my service gets the job done really quickly. I believe the trigger for my app was that the service was finishing before the system actually got around to showing a notification.The workaround/solution
I was able to get rid of all crashes. What I did was to remove the call to
stopSelf()
. (I was thinking about delaying the stop until I was pretty sure the notification was shown, but I don't want the user to see the notification if it isn't necessary.) When the service has been idle for a minute or the system destroys it normally without throwing any exceptions.Even after calling the
startForeground
inService
, It crashes on some devices if we callstopService
just beforeonCreate
is called. So, I fixed this issue by Starting the service with an additional flag:and added a check in onStartCommand to see if it was actually started to stop:
P.S. If the service was not actually running it will start the service first which is an overhead.