While it seems there are a few questions on here regarding Android 12 service restrictions, I have yet to see one specific to this use case.
Background: I am starting a foreground service to handle a very long running background media player (Exoplayer). Due to the setup of the app, I cannot use the built in notification manager from exoplayer. However I am seeing an odd behavior from Crashlytics. I am getting ForegroundServiceStartNotAllowedException
While the app is undoubtedly in the foreground. Per the logs, it is easy to see the user is navigating the app within a second of the startForeground
call.
I am also listening to
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event)
to ensure the app is in a foreground state.
I am beginning to run out of ideas as to what would cause this. As you can see by the timestamps, less than 1 second had gone by. The app has no use cases where the service could even accidentally be started from the background.
Thanks
Edit:
I am also declaring my service type:
<service
android:name=".service.SoundPlayerService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="mediaPlayback"
android:stopWithTask="false">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
if (!audioFocusTakenBackground && Application.instance.isAppInForeground) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(
ONGOING_NOTIFICATION_ID,
builder.build(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
)
} else {
startForeground(
ONGOING_NOTIFICATION_ID,
builder.build()
)
}
}
Edit: Device State tab suggested by @Arlind
One thing that's looking promising (I won't mark anything as answered until I get more data in) is by adding this bit to the notification builder:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
foregroundServiceBehavior = Notification.FOREGROUND_SERVICE_IMMEDIATE
}
Then to prevent crashes but still be notified of an issue I wrapped the startForeground
in a try/catch that posts to crashlytics so i know there's an issue:
if (!audioFocusTakenBackground && Application.instance.isAppInForeground && !isForegroundActive) {
isForegroundActive = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
startForeground(ONGOING_NOTIFICATION_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
true
} catch (e: Exception) {
Timber.e("Unable to start foreground: ${e.message}")
FirebaseCrashlytics.getInstance().recordException(e)
false
}
} else {
try {
startForeground(ONGOING_NOTIFICATION_ID, builder.build())
true
} catch (e: Exception) {
Timber.e("Unable to start foreground: ${e.message}")
FirebaseCrashlytics.getInstance().recordException(e)
false
}
}
}
Note that in the area where Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
, it adds that the notification is a FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
. According to the google docs here: https://developer.android.com/guide/components/foreground-services#notification-immediate this should be enough to initially show the notification. I'm curious if some implementations don't use or listen to that.
I will update this when I get more data, but for now my crashes have subsided and I am not seeing any logging from the catch blocks in crashlytics. Hopefully someone else can use this and verify my findings.
EDIT:
After a few days my crashes from this error have gone down to 0 and no noticeable logs from the catch's have been observed. Finally calling this one closed
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With