media: MediaLibraryService throws ForegroundServiceDidNotStartInTimeException
Media3 Version
1.0.0-beta02
Devices that reproduce the issue
Firebase crashlytics report these devices:
- Galaxy Note20 running Android 12
- Galaxy S21 FE 5G running Android 12
- Xiaomi 11T Pro running Android 12
- Redmi Note 9 Pro running Android 11
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
It’s happened on some devices. I think It has related to MediaController not properly handling the service.
Expected result
not crash?
Actual result
Fatal Exception: android.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{ac0645b u0 player.PlaybackService}
at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2147)
at android.app.ActivityThread.access$2900(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2376)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
Media
Bug Report
- You will email the zip file produced by
adb bugreport
to dev.exoplayer@gmail.com after filing this issue.
About this issue
- Original URL
- State: open
- Created 2 years ago
- Reactions: 16
- Comments: 148 (48 by maintainers)
Commits related to this issue
- Add suppression reason for unsuitable audio route. A follow up to stopping speaker playback with a Player decorator from https://github.com/androidx/media/issues/15. It looks like we will need to ch... — committed to androidx/media by yschimke 2 years ago
- Add suppression reason for unsuitable audio route. A follow up to stopping speaker playback with a Player decorator from https://github.com/androidx/media/issues/15. It looks like we will need to ch... — committed to google/ExoPlayer by yschimke 2 years ago
- Precedence for app provided media button receiver This change selects the best suited media button receiver component and pending intent when creating the legacy session. This is important to ensure ... — committed to androidx/media by marcbaechinger a year ago
- Precedence for app provided media button receiver This change selects the best suited media button receiver component and pending intent when creating the legacy session. This is important to ensure ... — committed to androidx/media by marcbaechinger a year ago
- Allow `MediaLibraryService` to reject the resumption notification To reliably reject the System UI playback resumption notification on all API levels (specifically API 30), the backward compatibility... — committed to androidx/media by marcbaechinger a year ago
- Add MediaButtonReceiver for Media3 The media button has API support with `Callback.getPlaybackResumption()` that apps need to override to provide a playlist to resume playback with. Issue: androidx/... — committed to androidx/media by marcbaechinger a year ago
- Allow `MediaLibraryService` to reject the resumption notification To reliably reject the System UI playback resumption notification on all API levels (specifically API 30), the backward compatibility... — committed to androidx/media by marcbaechinger a year ago
- Stop the service in onTaskRemoved If the player isn't set to play when ready, the service is stopped and resources released. This is done because if the app is swiped away from recent apps without t... — committed to PaulWoitaschek/Voice by PaulWoitaschek a year ago
- fix: dont export PlaybackService to prevent ForegroundServiceDidNotStartInTimeException https://github.com/androidx/media/issues/167 — committed to bcc-code/bccm-player by andreasgangso 10 months ago
- fix: onUpdateNotification to fix ForegroundServiceDidNotStartInTimeException https://github.com/androidx/media/issues/167 — committed to bcc-code/bccm-player by andreasgangso 10 months ago
- Set notification foreground service behaviour starting with API 31 When the foreground service type is set to `mediaPlayiback` this shouldn't be required. However, some reports from users say that se... — committed to androidx/media by marcbaechinger 10 months ago
- Use media button broadcast receiver above Android 31 This change avoids using a framework API that is deprecated since API 31 and works around difficulties with this deprecated API on devices from so... — committed to androidx/media by marcbaechinger 10 months ago
- Fix #167 — committed to jackyhieu1211/media by jackyhieu1211 10 months ago
- Use media button broadcast receiver above Android 31 This change avoids using a framework API that is deprecated since API 31 and works around difficulties with this deprecated API on devices from so... — committed to v-novaltd/androidx-media by marcbaechinger 10 months ago
- Set notification foreground service behaviour starting with API 31 When the foreground service type is set to `mediaPlayiback` this shouldn't be required. However, some reports from users say that se... — committed to hugohlln/media by marcbaechinger 10 months ago
- Use media button broadcast receiver above Android 31 This change avoids using a framework API that is deprecated since API 31 and works around difficulties with this deprecated API on devices from so... — committed to hugohlln/media by marcbaechinger 10 months ago
- Upgrade android media library (#92) A new version, 1.2.0, of the android media library was [just released](https://github.com/androidx/media/releases/tag/1.2.0). This release includes several fixes... — committed to dharmaseed/dharmaseed-android by bb4242 7 months ago
- Attempt to fix frequent MiniPlayerFragment ANRs seen in production (#96) For background on the issue, and why this change may help, see https://github.com/androidx/media/issues/890. I had hoped that... — committed to dharmaseed/dharmaseed-android by bb4242 6 months ago
I’m on version
1.0.2
. Seeing more than 100 of these crashes per day on Firebase and also getting user reports about playback randomly stopping when app is in background or phone is locked.Mostly Samsung devices on android 13 but also seeing it for android 11 and 12.
Is there any plan to fix this?
And could the playback stopping be due to “battery optimization” settings killing the app on some of these devices? If so is there a solution for that?
Thanks everyone for the provided information. @marcelpallares Looks like your app is doing the right thing.
I can repro this with the demo app on a Samsung Galaxy A51.
Repro steps with session demo app:
onTaskRemoved()
the app stops the service withstopSelf()
which triggersonDestroy()
where resources are released.Media output
play
button for the session demo (see screenshot at the end)play
MediaSession.Callback.onPlaybackResumption()
. Playback doesn’t start and service doesn’t go to the foreground.–
The interesting part is what shows up on this device when looking at the sysdump after the app was terminated.
While on a Pixel 6 API 33 it shows:
The latter is the expected output as per these lines in
MediaSessionLegacyStub
of Media3 that I verified is executed on both devices before the player is released and the app terminates.Looks like a different behavior than expected after setting the MBR to null. We will investigate some further.
Fixing
The fix is to achieve that the
Last MediaButtonReceiver
is set to null on all devices and all API levels as intended by Media3. Mdeia3 must make sure this works. We investigate on our end and file a bug and talk to Samsung if required for a solution.I wouldn’t recommend other fixes suggested above. It may remove the stack traces from the statistics, but the user sees the same play button that doesn’t work.
Besides the unfortunate fact that there is this play button that doesn’t work, this should not affect the proper functioning of your app in other areas. It is also restricted to these devices, although this is certainly an important case to take care of for this important vendor.
Available workaround
The only workaround I know for devices that exhibit this behavior with the current released Media3 version is implementing
MediaSession.Callback.onPlaybackResumption()
to return at least one playable item. Then playback starts, the service goes into the foreground and the exception is not thrown.Screenshot of the button from the notification drawer:
For fixing crash: If you are using MediaSessionService, try overiding onUpdateNotification and using startInForegroundRequired always true
fixes the crash.
I think the reason is that, if you start your media and keep it is pause state and move your app in background and then kill the app. The service will be created but startForegroundService() will not be called until you play the media or it will remove your service from foreground state but will not remove the notification. I tried the same on Sample Media Session app, and issue was reproducible with the same steps.
startForegroundService makes an implicit promise that the Service will call startForeground(int, android.app.Notification) once it begins running otherwise this ANR will be triggered.
On reading the internal implementation, using this flag true here works because:
Yours media controller is set and and playback state might be ready, but video is not playing so getPlayWhenReady() will be false. Hence, this will remove your service from foreground state but will not remove notification if you don’t send startInForegroundRequired to true.
However, I think media3 should provide a proper fix for this case. Let’s wait for @marcbaechinger 's inputs on this.
We should do something about this or at least state in the docs about recommended way of handling the issue.
As currently it leads to dozens of crashes out of blue once an app hits production and devs have no way of expecting this behavior if they are not thinking about rare cases such as this.
Well, this is the way we can emulate how system kills the process due to some period of inactivity, nobody really expects users to do that.
@yebonkim @s6joui @ziem
I tried solution of @agnihotriayush . It worked good. I’m testing more. Thanks @agnihotriayush
@marcbaechinger Hi I want to apply this commit to my application. but it seems version 1.2.0-ahpha1 and 1.1.1 does not include this commit. So can you create a new version? Thank you
Seeing the same issue here. 100% Android 13, and mostly Samsung devices.
@jackyhieu1211 Thanks for your report and the evidence of problems on some devices. Very useful.
According to this doc, a notification of a foreground service that is having a
foregroundServiceType
ofmediaPlayback
is always posted immediately. So setting the foreground service behaviour on the notification seems not to be required.An app needs to set this in it’s manifest, Media3 can’t do this for an app. The session demo app has set it here.
However, according to your report this is not sufficent on some devices. We will add setting the foreground service behaviour accordingly in
DefaultMediaNotificationProvider
. This shouldn’t harm in any case and if we can do this for users on the library side we should. The change will land on themain
branch soon.Out of curiousity: Did you set the foreground service type to
mediaPlayback
in the manifest when you’ve seen this problem? And did you actually useDefaultMediaNotifciationProvider
?After release. This solution reduces crash rate ~10%
Thanks for reporting and precise repro steps including API version! I can repro this with an emulator API 30/Android.
For context, API 30/Android 11 introduced media controls including playback resumption with a notification provided by System UI. See sections
Media controls
andPlayback Resumption
of this blog post for the legacy API. This applies if your service is exported with actionandroid.media.browse.MediaBrowserService
in the app manifest for backward compatibility.Looks like this is an API 30 specific misbehavior that the
PlaybackService
of the demo app does not properly handle the attempt of System UI to provide a playback resumption notification. The ‘stale notification’ is actually not a notification from the demo app or the Media3 library, but a notification provided by System UI.After adding some additional log statements I can see that System UI attempts with package
com.android.systemui
to initiate playback resumption:We can verify a few things (sorry for oversharing, it may be helpful for readers).
The log shows that the
PlaybackService
has been accessed by system UI to get ‘recently played information’. It also shows that after the click on the play button of the ‘stale notification’, the system attempts a restart by creating aMediaBrowserCompat
connecting against our service.adb -s emulator-5560 shell dumpsys notification | grep -e "NotificationRecord"
before and after step 5 of the repro steps to see whether the notification of the demo app package got removed.adb -s emulator-5560 shell dumpsys media_session
before and after step 5 shows that the session was released and media button receiver intent have been cleared.Handling System UI playback resumption
To avoid problems with the observed attempts of System UI, the demo app and other apps needs to properly handle playback resumption attempts from System UI.
Currently, the session demo app does not support playback resumption and should not accept System UI’s attempts to access the
PlaybackService
. There are various ways to do that, some that work for me with the session demo are:MediaLibraryService
can setexport="false"
in the service in the manifest. The service is then not visible to SystemUI and it won’t even try to connect:android.media.browse.MediaBrowserService
from service in manifest if you do not want backwards compatibility withMediaBrowserServiceCompat
(for apps that only need to support Media3 controllers).Alternatively, apps can fully implement playback resumption as documented for the legacy API or implemented by UAMP in the Media3 branch like here and here. This includes implementing resuming playback when the service is started as described fro 1.0.0 in the comment above.
We are currently working on supporting playback resumption with BT headsets and System UI notification with library support and the session demo app for 1.1.0. and documenting this on DAC.
I’m seeing this issue, and have never declared. <action android:name="android.intent.action.MEDIA_BUTTON" />
Feels like there are multiple aspects to this issue, this closes the door on one of them.
Thanks for the explanation. I don’t know the details why the framework decides to not call any lifecycle method when this flag is turned on. I don’t find this a very useful behavior to be honest. Said this, I’m unclear about the reasons, so I may be just me being ignorant and uneducated.
The framework, btw, also doesn’t call
onDestroy()
in such a case. This means that an app (or the library) can’t really properly clean up the service when this flag is set.I will investigate some further but as it looks like, the recommendation for now is to just not set this attribute to
true
. I’ll make sure this is documented accordingly.We plan to provide a default implementation of
MediaSessionService.onTaskRemove()
. Then the app doesn’t need to overrideonTaskRemoved()
, if the default implementation provides the desired behavior. Still thestopWithTask
attribute can’t be used.The implementation of
onTaskRemoved()
to achieve this is as follows:You need to make sure the player is paused, because if playing, the service is in the foreground in which case calling
stopSelf()
is a no-op. The above snippet assumes you have implementedonDestroy()
to release session and player.onDestroy()
will be called when the service is stop self’d.@jackyhieu1211 Thank you for your information. I will release new version with that solution and share the result here
I use PlaybackService same as demo.
91% crashes on Samsung device 99%~100% crashes on android 12 and android 13
This is firebase crashlytics
I have reproduced the crash on my Samsung device
I have tried doing the debug as below and I am not getting any more crashes. You can try
Full my code
I will release on my app soon. I will update the latest information later Hope it’s useful
@s6joui I’m on
1.1.0-beta01
and I have a few crashes due to this. This is a background crash, the user interacts with the notification but the application can’t start playback, and the crash happens. In this comment from one of contributors there is a solution for playback resumption which helped me on some devices. But I discovered that for some Samsung devices, We have to useWakeLock
to wake the device to playback actually starts playing. I don’t have Samsung devices with Android 13, and 99% of crashes happen on that devices and most of them are 5G. So I couldn’t test and fix this for my app.And Yes, Battery Optimization is the reason to kill your app. You have to check with
PowerManager.isIgnoringBatteryOptimizations(packageName)
and if not, show a dialog and ask the user to disable Battery Optimization for your app.Not sure if someone mentioned it before, but here are the steps to reproduce
ForegroundServiceDidNotStartInTimeException
/ ANR: Context.startForegroundService() did not then call Service.startForeground()… in the demo-session app:adb shell am kill androidx.media3.demo.session
in your terminalThanks for the logs.
I’m not sure whether changing the media button intent to use
startService
is the right approach, because in theplay
case we actually want to start the service in the foreground. We would then run into another exception in such a case.For your reported case documented by the logs above I think the service has been crashed by the system:
This happens because the service wasn’t terminated when the user has removed the app from the list of tasks (aka. the user has killed the app). If the user does this while the service is not playing (aka the service is not in the foreground), the service needs to be properly terminated which you can do in
onTaskRemoved
.I think the log line from above tells us that the user has removed the app from the list of recent apps and the
ActivityManager
crashes the service and restarts the service. I think then your service re-creates the session which puts theMediaButtonReceiver
back in place. When the user then uses the media button on the BT headset, the session tries to start playback. The session exists but the player is still inSTATE_IDLE
, meaning it has an empty playlist and is not yet prepared. I conclude this from the logs at the moment when the BT command arrives that reports the session state:state=1 => STOPPED, speed=0.0 => paused
So, the BT event now arrives and tries to start playback. If this would work, then the service is put in the foreground and we are all happy. However, the player is in state
STATE_IDLE
and can’t start playback and accordingly the service is not put to foreground and produces theForegroundServiceDidNotStartInTimeException
that you report. I would expect this being a problem not only on Android 13 but since Android 8.So unfortunately the answer to this report is that it’s a bit more complicated and a bit more work for apps that want to support resuming playback after the app has been terminated by the user. The reasons is not that Media3 folks wants it like that, the reason is that Media3 needs to follow the platform restrictions to not make problems for apps. Full playback resumption support includes these three things:
If you see this line
something isn’t well.
MediaButtonReceiver
to enable playback resumption.MediaLibraryService/MediaBrowserService
.Summarizing this investigation I don’t think there is a change in the service (like moving to an
Intent
fromgetService()
) that would help. The current implementation works including playback resumption as explained above and there is no change that could make things easier for developers without running into exceptions that come from the restrictions around foreground services.If there is a chance to make life easier for developers we are very happy to do that but as of now I don’t know of such a case. Please tell me if you think differently.
***** EDIT ***** I found the reason. when you play a song and then pause it and close the app the notification remains If you click on play, after a few seconds it will crash. service is not foreground but notification is not dismissed and the problem is when pressing the play button it will crash
Hi, I reproduce the crash with media session demo app here is the stack trace. I don’t know if It’s the exact same, but in bottom of crash it contains the
ForegroundServiceDidNotStartInTimeException
exception. It happens in the background playing when pressing play/pause a few times On both the Lock screen and unlocked. Also, the crash is insanely reporting in crashlytics for me!I’m using
MediaSessionService
in my app (not really the same with this issue discussion but I think it’s the same issue, sorry about that) and I tried to implementonPlaybackResumption
after reading the whole discussion thread. But I still able to reproduce the issue by these steps.android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
I thought that supporting
onPlaybackResumption
would prevent the crash but it didn’t. Any idea what I should be doing nex? Because this issue is the top one in crashlytics. Any help would be appreciated.@marcbaechinger Hi
My AndroidManifest
Fatal Exception: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{a34774e u0 com.music.video.player/com.service.PlaybackService}
I have to stop the MediaSessionService when the app is swiped out of the recent apps.
stopWithTask= true was the first thing I tried but this didn’t remove the notification / stop the service when the playback was paused.
Calling stopSelf() inside onTaskRemoved seems to work but onTaskRemoved is only called if I remove stopWithTask= true from the Manifest first.
Could you maybe explain why there is a difference in the first place? I thought I would only have to use onTaskRemoved if I had to execute more code than just stopSelf(), and for just stopping the service stopWithTask is the better choice.
It’s unrelated to the Jetpack Media library, but one of possible reasons for lots of crashes with “Context.startForegroundService() did not then call Service.startForeground()” on Samsung devices is their battery saving options. I could reproduce such crashes by opening my app in the system settings, selecting “Battery” and unchecking “Allow background activity”. After that, requesting the service to start and immediately folding the app makes this crash happen.
@marcbaechinger
This is the stack trace (we shared it a few months ago and have been following this issue since hoping for a solution).
As with everyone else, most of the devices reported are Samsung (96%) and Android 13/14 only.
Exactly the same issue for me. Android 13, mostly Samsung.
Yes, indeed. Option 2 was rubbish. Sorry. I have removed it from the comment above. The other two options work for me though.
I’ll investigate how to tell System UI not to do a notification on all API levels with the
isRecent
contract. Will update here when I have news.In #299 the question was raised how an app can start playback when started by a BT headset
play
command with a media button receiver in place. In such a case the service is started with anIntent
with actionACTION_MEDIA_BUTTON
and an app needs to start playback to not run into aForegroundServiceDidNotStartInTimeException
.There is currently no API for this. We are planning to add a media button receiver to Media3. When we do this we will probably add some API that makes the process easier. This is not a preview of that API, but simply a solution how apps can start playback after being started with a pending intent with action
ACTION_MEDIA_BUTTON
from a BT headset to avoid theForegroundServiceDidNotStartInTimeException
.What worked for me in the session demo is the following. Roughly this includes:
SharedPreferences
to store and restore a basic media item.onStartCommand
and detects when theplay
key event is sent by the BT headset and the player has an empty playlist.super.onStartCommand
. The library will then prepare the player and callplay
with the first item. When thisplay
command succeeds, the service is started in the foreground that prevents theForegroundServiceDidNotStartInTimeException
exception when started from BT headsets.The code below shows how I implemented this as a prototype with the
PlaybackService
of the session demo app. This is not a recommendation of the best way to do it, but a proof of concept that worked well for me when I tested with the session demo app. If you experience theForegroundServiceDidNotStartInTimeException
when started from BT headsets, this can be a way to avoid that.This is a minimal sample that show the idea only. You may want to persist more data like the category, the current position and the like. You also want to sanitize (eg. null-checks when restoring data) the code better than this example 😃
@AndrazP @tfighieraFreebox
Is you app using a
androidx.media.session.MediaButtonReceiver
? If your app is having a media button receiver, then the system may start your service and then sends an Intent with actionandroid.intent.action.MEDIA_BUTTON
.I’m asking because in such a case the service is allowed to be started as a foreground service (
ContextCompat.startForegroundService(...)
) as per exemption. Your service then needs to handle that intent and immediately start playback to make theMediaNotificationManager
start in the foreground.This is a potential source for a
ForegroundServiceDidNotStartInTimeException
that I was just able to repro. Just adding this as for your information and investigation.@yschimke This issue is about a
ForegroundServiceDidNotStartInTimeException
of theMediaSessionService
. My understanding/hypothesis is that this is related to the first command arriving inonStartCommand
as a pending intent when the service is not yet running (onCreate
called immediately beforeonStartCommand
). My understanding is based on a possibly faulty code path that I found and described above and that the exception is observed on Android 12 and 11 where the notification still sends pending intents (as opposed to Android 13). Where do you see the risk of a race condition with another intent or media session command in such a case when the service is not yet started?By design, the service is started by creating a controller/browser and binding to the service. The service shouldn’t be started by a pending intent (not
Context.startForegroundService(intent)
) that are only coming from the notification - which needs a running service.For this reason, I agree that this is about a race condition or an invalid state but elsewhere (stale notification?). I couldn’t repro, because I do not understand from where a pending intent for
PAUSE
arrives when the service is not running. When the service is stopped, the notification is removed and there shouldn’t be a way to send aPAUSE
intent in this case. If such an intent is sent by an app, the app is just not using the service correctly I think. Not saying this is the case, as I have no evidence that this is an app problem.I agree that I’m not sure that this fixes the problem, but I think it removes the
ForegroundServiceDidNotStartInTimeException
(admittedly to the expense of another Exception that we hopefully better understand). Because in such a case of aPAUSE
command when the service is not yet started, we probably now are at risk of aForegroundStartNotAllowedException
.If you have any way to repro this
ForegroundServiceDidNotStartInTimeException
please let me know. I’m thankful for any input that makes me understand better how this exception is produced.Hello, thank you for your quick answer. I looked into the demo session automotive app and I figured out that the
MediaSessionServiceListener
overridesonForegroundServiceStartNotAllowedException
as follows:Can you please explain why you override this exception and why you create a notification inside?
FYI: I tried to reproduce the issue in the demo automotive application and I was unable to reproduce it.
Thank you!
Hello,
I’m facing the same issue when I start a media service from an automotive application. I’m using an automotive emulator API 32. The compile and the target sdk are the same 34. I’m using media3 1.2.0 version.
Steps to reproduce the
ForegroundServiceDidNotStartInTimeException
:android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground()
The
startForegroundService
is called fromonCreate()
in application. Is there something that I’m doing wrong?I remain available if you need more information about this issue.
Thank you!
@myolwin00
In step 3 there should not be a notification. I have done these steps two or three times with the demo app in the last months (probably four times even 😉) and there is no stale notification.
However, your report is not really actionable I’m afraid. Can you confirm these steps work to repro the problem with the demo app? If this is the case can you give me some more details around the API level and what device you are using?
If you can not repro with the demo app, please review whether your app terminates the service in
onTaskRemoved
in a way that is sensible for your use case (See this comment also).This is what I got as a support request.
@marcbaechinger Hi. Thanks for your suggestion. After remove
<action android:name="android.intent.action.MEDIA_BUTTON" />
My application has DAU ~60K users
The error has completely disappeared on Android 13. This is wonderful ❤️️❤️️❤️️❤️️
But the error still appears in Android 12 and lower. I will try to reproduce the error and send it to you
@marcbaechinger
Not at all! I’m happy to provide as many insights as I can to get this resolved. Even if needed, happy to schedule a quick call to walk you through the codebase. We have never been able to reproduce the issue ourselves btw.
We have use
stopSelf()
to stop the service. We also callplayer.stop()
inside theonTaskRemoved()
method. We don’t manually stop the service in any other way at any point, we callcontroller.stop()
using the MediaController when an audio session is finished, and if we need to start another session we set up the newmediaItems
and callprepare
andplay
. So the service is always around unless the app is killed. Is this a bad practice?We also use onDestory() to release the
player
andmediaSession
.No, we don’t. See above both methods.
None of them.
@marcbaechinger in my case, both solutions (android:exported=“false” and super.onUpdateNotification(session, true)) did not help.
After looking at the two commits that helped you. One change makes the service always run in the foreground. The other does not export the service anymore.
From this, the crashes could be from external apps that start your service, which makes the service create a session that is returned by
MediaSessionService.Calback.onGetSession(controllerInfo)
. This then callsonUpdateNotification(session, boolean startInForeground)
that you override by always passingtrue
some further.If my reasoning is correct (which isn’t sure with the available inormation), then the reason for your crashes can be an external app that starts the service but does not call
play
when starting. This, by design, leads to aForegroundServiceDidNotStartInTimeException
.Both of these commits prevent this. Not exporting prevents external apps from seeing and starting your service. Always passing
true
intosuper.onUpdateNotification(session, true)
prevents the service to not be put into the foreground when started with something else thanplay
.Yes. That’s interesting.
If you don’t export the service, then no other app than your own app sees the service. I’m not sure for users with system-privilege (like System UI), but other external apps would not see the service in the
PackageManager
nor would they be able to crash your app with aForegroundServiceDidNotStartInTimeException
in such a case. So given the reason for your crashes were external apps, it seems evident that not exporting the service works, the question is if the implications with this are intended and also, why external apps were trying to start your service without you knowing it and giving consent.That’s amazing. I’m excited for you as well. If your app has a lower crash-rate by not exporting the service, then is it likely that those users that produced the crash before, where trying to access your service from external apps?
If you don’t have such external users, then I would definitely not export the service. You need to test whether System UI still works though. I would guess the notification works without a problem because the notification only uses the
MediaControllerCompat
. If you are using the resumption notification of System UI starting with API 30 that is usingMediaBrowserCompat
, then I would test this thoroughly on all API level when not exporting the service.If you not export the service, you can probably also remove
because internally I’d guess you have Media3 controllers only.
Unfortunately, we can’t be sure because your fix seems to do several things. This change around not exporting the service though, is either not required (as in not fixing anything), or then the actual reason for the crashes you are seeing were external apps.
@whitipet I have reproduced the problem. If you want to try, follow the instructions here. LINK HERE
@jackyhieu1211 Strangely, this does not match the documentation. Either the documentation is wrong, or some manufacturers have decided to change something. I can’t reproduce this crash on my Pixel 7 Pro android 13, but according to Crashlytics, 99% of users are Samsung. In any case, I will wait for the release with the fix and try it. If it doesn’t work, I’ll add a request for notification permission.
for 2days, although we didn’t release hotfix version fully, Our service don’t have this crash! Thanks @agnihotriayush
For additional information, our product use mediaSession with exoplayer and don’t use mediaController
@marcbaechinger @tianyif We are still waiting for an input on this, to completely fix this issue. Initially I thought that my solution will keep the service in foreground and we will not experience this issue. We still have some users experiencing the issue. What should be the proper fix?
Hi @jackyhieu1211 I have same crash. Did you fix your crash by above code?
Thanks again for reporting @MaximillianLeonov . This is a bug on API 30 where the contract described in [1] is slightly different for rejecting the System UI playback resumption notification.
I have created #355 to track this.
[1] https://developer.android.com/guide/topics/media/media-controls#mediabrowserservice_implementation
I have not checked with the fix solution yet, but I will try it and let you know.
To me this is not really a solution because this is assuming that all apps that have a Browser Service and Library Service. Want apps to resume playback even when, in our case, it’s a news app that also does podcasts.
If the player has never discovered the podcast feature of our app and he would press a BT Button. It doesn’t make sense at all to start playing those.
I’m not sure if i get what you’re saying about ‘registered a receiver’ afaik there is no way of registering a button receiver or deregistering it for that matter. Because if we could do that i would love to do that.
Do you know of a way to remove the registered intent from mediassession that comes up in
Additionaly this error mainly occurs when targeting 33.
Note: for now we’re investigating reverting the media3 investment because we have way to many users in production that are expierencing these crashes. 5k on a 5% rollout, which is unacceptable for a library that is marked as stable.
I found two way to reproduce the crash. With demo-session from this project (100%) :
Since onTaskRemoved is called but onDestroy is not from PlaybackService, the mediaLibrarySession is not released and mediaButtonIntent is not canceled from MediaSessionImpl.
With uamp, branch media 3 :
This case is different, onTaskRemoved and onDestroy are not called. Since uamp doesn’t release MediaBrowser in Activity onStop, the service is not destroyed.
A possible solution could be a combination of the two projects. In the demo-session app, you can release the mediaLibrarySession in onTaskRemoved, and in uamp, you can release the MediaBrowserService in onStop from the Activity.
However, this solution doesn’t meet my needs and seems quite fragile.
Do you see any restrictions to stop using getForegroundService in MediaSessionImpl ?
I would sugest :
Or same approach as before media 3 :
@marcbaechinger let me know if you need a more detailed bug report.
same here with beta3 and target sdk 33. Devices are 100% samsung with android 12 and 13
for Android 13 got this stacktrace:
and for android 12:
It occurs 100% in background and considered as a
repeated crash
by firebaseThanks for digging some further. That give me some further data points.
Yes, indeed, these cases are always about closing the app and having only the service playing in the background. As soon as your app is in the foreground with a controller connected you are bound to the service, and you will never see such an exception.
With the default behaviour of the
MediaSessionService
(your app does not overrideupdateNotification()
), I don’t think thatplay
should produce aForegroundServiceDidNotStartInTimeException
, because after you pressed play,playWhenReady
is true and the player is notSTATE_IDLE
which results inservice.startForeground()
being called. Withplay
I would only expect aForegroundServiceStartNotAllowedException
in some cases but not when pressingPLAY
on a notification on Android 12 (PendingIntent
with exception) and Android 13 (MediaSession
with exemption).I still think it’s the
PAUSE
case for which we will provide a fix.