Android 12 ForegroundServiceStartNotAllowedException 在前台?

虽然这里似乎有一些关于 Android 12 服务限制的问题,但我还没有看到一个特定于这个用例的问题。

背景:我正在启动一个前台服务来处理一个运行时间很长的后台媒体播放器(Exoplayer)。由于应用程序的设置,我无法使用 exoplayer 的内置通知管理器。但是,我看到 Crashlytics 的奇怪行为。我得到 ForegroundServiceStartNotAllowedException 虽然该应用程序无疑处于前台。根据日志,很容易看到用户在 startForeground 调用后的一秒钟内浏览应用程序。

我也在听

override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event)

以确保应用程序处于前台状态。

logs

crash

我开始想不出什么会导致这种情况。从时间戳可以看出,不到 1 秒就过去了。该应用程序没有使用案例,服务甚至可能意外地从后台启动。

谢谢

编辑:

我还声明了我的服务类型:

        <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()
                )
            }
        }

编辑:@Arlind 建议的设备状态选项卡

Device States

stack overflow Android 12 ForegroundServiceStartNotAllowedException while in Foreground?
原文答案
author avatar

接受的答案

看起来很有希望的一件事(在我获得更多数据之前,我不会将任何内容标记为已回答)是将这个位添加到通知构建器中:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    foregroundServiceBehavior = Notification.FOREGROUND_SERVICE_IMMEDIATE
}

然后为了防止崩溃但仍会收到问题通知,我将 startForeground 包装在发布到 crashlytics 的 try/catch 中,因此我知道存在问题:

        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
                }
            }
        }

请注意,在 Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q 的区域中,它添加了通知是 FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK 。根据此处的谷歌文档: https://developer.android.com/guide/components/foreground-services#notification-immediate 这应该足以初步显示通知。我很好奇某些实现是否不使用或不听它。

当我获得更多数据时,我会更新它,但现在我的崩溃已经消退,我没有看到 crashlytics 中的 catch 块中的任何日志记录。希望其他人可以使用它并验证我的发现。

编辑:

几天后,我因此错误导致的崩溃已降至 0,并且未观察到来自 catch 的明显日志。终于把这个关了


答案:

作者头像

切勿尝试使用您自己的服务播放音频。始终使用此处描述的 MediaSession API: https://developer.android.com/guide/topics/media-apps/audio-app/building-an-audio-app

作者头像
Application.instance.isAppInForeground

这个变量有正确的值吗?也许这个变量得到了错误的值。你能检查一下吗?