Bound service crash with "Context.startForegroundService() did not then call Service.startForeground()" error
Solution 1
To expand on UdeshUk's answer - any use of MediaButtonReceiver
(either building pending intents or just receiving media button intents) can result in your service being called with startForegroundService
, because MediaButtonReceiver.onReceive
starts your service in that way on Oreo. I haven't seen this documented anywhere.
Solution 2
I found the problem. In my notification I have set
setDeleteIntent(MediaButtonReceiver.buildMediaButtonPendingIntent(service, PlaybackStateCompat.ACTION_STOP))
So when user removes the notification it calls startForegroundService() because I called stopForeground() previously when pausing.
To overcome, I used a custom pending intent and handled it in the onStartCommand()
instead of MediaButtonReveiver's PendingIntent
Solution 3
You must call this method inside your Service class onCreate() method:->
private void startServiceOreoCondition(){
if (Build.VERSION.SDK_INT >= 26) {
String CHANNEL_ID = "my_service";
String CHANNEL_NAME = "My Background Service";
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME,NotificationManager.IMPORTANCE_NONE);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setCategory(Notification.CATEGORY_SERVICE).setSmallIcon(R.drawable.ic_tgc_icon).setPriority(PRIORITY_MIN).build();
startForeground(101, notification);
}
}
Solution 4
Late to the party, but as was mentioned before, it's the MediaButtonReceiver
; it has this code:
@Override
public void onReceive(Context context, Intent intent) {
...
startForegroundService(context, intent);
...
}
I'm using the receiver in a bound service, so I created a class that has the exact same code as MediaButtonReceiver
, except for this line. I replaced it with:
context.startService(intent);
Solution 5
From the docs 8.0 Behavior Changes
The system allows apps to call Context.startForegroundService() even while the app is in the background. However, the app must call that service's startForeground() method within five seconds after the service is created.
So, you have to call startForeground inside onCreate() for your service.
Related videos on Youtube
![UdeshUK](https://lh5.googleusercontent.com/-GezJ4zu3jQ0/AAAAAAAAAAI/AAAAAAAAAp8/z5khmwqs3Ew/photo.jpg?sz=256)
UdeshUK
A research intern at SCoRe Lab and a computer science student at the University of Colombo School of Computing. Interested in ML, Blockchain, mobile, and web development. Loves coffee.
Updated on November 05, 2020Comments
-
UdeshUK over 3 years
I'm currently working on audio playback app and I'm using a started bound service to play music in background. I start and bind to the service using following code.
val intent = Intent(context, MusicService::class.java) context.startService(intent) context.bindService(intent, serviceConnection, 0)
It gets promoted to foreground when playing and gets demoted when music is paused.
// onAudioPlay service.startForeground(NOTIFY_ID, notification) // onAudioPause service.stopForeground(false)
Service work fine up to now. But when the notification is swiped(removed) by the user in the paused state, the service crashes after few seconds giving this error.
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.myplayer, PID: 4380 android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground() android.app.ActivityThread$H.handleMessage(ActivityThread.java:1775) android.os.Handler.dispatchMessage(Handler.java:105) android.os.Looper.loop(Looper.java:164) android.app.ActivityThread.main(ActivityThread.java:6541) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
This only happens on Oreo and I already read about the background limitations in Oreo. But following points bugs me.
- This service is a bound service(which aren't affected by limitations)
- I never use Context.startForegroundService() to start the service.(and don't want to use it)
- The service doesn't crash when it gets demoted from foreground, it's happens when removing the notification.
Why is the service is crashing? What am I doing wrong? I'm very thankful if someone tell me whats happening here.
-
Yuchen over 6 yearsThis is interesting. I suggest you post your solution as an answer and mark it as accepted instead of editing the question. It is more clear to the future reader as well.
-
UdeshUK over 6 years@YuchenZhong Thanks for the suggestion. I added an answer.
-
UdeshUK over 6 yearsYeah. But this happen while my activity is open. So my app isn't in the background. And also I don't start the service with startForegroundService().
-
Steve M about 6 yearsCan you explain how that line of code calls startForegroundService() implicitly? I have similar problem where I never call it and it might provide clues. Thanks.
-
gxcare over 5 yearsI have the same issue calling MediaButtonReceiver.handleIntent, and there is a note in the docs "Once the service is started, it must start to run in the foreground". It was quite cryptic until reading your answer.
-
th3hamm0r over 5 years@SteveM the above line creates a
PendingIntent
which targets theMediaButtonReceiver
, which then may call your service withstartForegroundService
(which also depends on how you configured your intent filters in the manifest). So the best solution to avoid thosestartForegroundService
-calls is to avoid theMediaButtonReveiver
, see stackoverflow.com/a/50629196/1394330 -
RJ Aylward almost 5 yearsIf you register a MediaButtonReceiver in your manifest Android can try and restart your media session by calling startForegroundService, and if you don't show a notification soon enough in this case it will cause the ANR. You can opt out of this behavior as described in the [docs] (developer.android.com/guide/topics/media-apps/…)
-
Kris B over 4 yearsDo you know if using
setMediaButtonReceiver(null)
will cause any issues with using external media controls? I updated my code to use this and it still recognizes button commands from my Bluetooth headset but it seems odd to just set it to null. -
Kris B over 4 yearsReally nice of Google to make us aware of this. What happens if Google ever modifies the code in
MediaButtonReceiver
? Do you have copy the code into your project everytime there are any changes to it? -
Kris B over 4 years@UdeshUK I'm confused when you said you created a custom pending intent. Wouldn't just adding a notification to
onStartCommand()
in yourMediaBrowserService
work? -
mhashim6 over 4 yearsI guess so, I guess they did that as some kind of enforcement; you can only access the media button in foreground. That was shortsighted though, the entire services api is a pain any way.
-
Kris B over 4 yearsI just set
setMediaButtonReceiver
tonull
and that seemed to work as mentioned here:developer.android.com/guide/topics/media-apps/… I was worried it would effect handling media controls from a Bluetooth headset but it doesn't. -
UdeshUK over 4 years@KrisB Sorry I don't use a
MediaBrowserService
. I have a custom music service to handle playback and handle media files. -
mhashim6 over 4 yearsAre you still able to listen to media button's events?
-
Андрей Воробьев over 4 years@KrisB But it is actual only for Android 5.0 (API level 21) and higher?
-
Андрей Воробьев over 4 years@RJAylward But it is actual only for Android 5.0 (API level 21) and higher?