Android 13下Media3 MediaSessionService前台服务启动崩溃求助
问题描述
我开发了一款基于Media3 MediaSessionService的媒体播放器应用,核心实现与遇到的问题如下:
ExoPlayer初始化(Service的onCreate方法中)
mTrackSelector = DefaultTrackSelector(this) mTrackSelector.parameters = mTrackSelector.parameters .buildUpon() .setPreferredAudioLanguage("en") .setPreferredTextLanguage("en") .build() val mAudioAttr = AudioAttributes.Builder() .setUsage(C.USAGE_MEDIA) .setContentType(C.AUDIO_CONTENT_TYPE_SPEECH) .build() mPlayer = ExoPlayer.Builder(this) .setSeekBackIncrementMs(30000) .setSeekForwardIncrementMs(30000) .setTrackSelector(mTrackSelector) .setAudioAttributes(mAudioAttr, true) .setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT) .build()
MediaSession创建
mMediaSession = MediaSession.Builder(this, forwardingPlayer) .setId(System.currentTimeMillis().toString().takeLast(5)) .setCallback(librarySessionCallback).build()
测试与生产环境差异
- 测试环境(Android 8-14真机/模拟器):无需通知权限即可正常运行,Media3控制通知正常显示
- 生产环境:Firebase Crashlytics上报Android 13设备出现以下崩溃:
Fatal Exception: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{4e0c02b u0 xx.xxxxx.PlayerService}
已尝试的操作
- 实现
MediaSessionServiceListener并重写onForegroundServiceStartNotAllowedException,但在自用Android13-14设备/模拟器上无法复现崩溃或触发该方法 - Gradle配置:
compileSdk 34、targetSdk 34 - 服务启动方式:
val mSessionToken = SessionToken(nInterface.getActivity(), ComponentName(nInterface.getActivity(), PlayerService::class.java))
AndroidManifest配置
<service android:name=".engine.notification.PlayerService" android:foregroundServiceType="mediaPlayback" android:stopWithTask="true" android:exported="true"> <intent-filter> <action android:name="androidx.media3.session.MediaSessionService"/> </intent-filter> </service> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
注意到YouTube Premium在Android13-14无需通知权限即可后台播放,请问:
- 我哪里出错了?
- 如何复现该崩溃?
问题分析与解决方案
1. 崩溃原因定位
这个崩溃的核心是服务启动后未在5秒(Android 12+规定时限)内完成startForeground()调用,结合你的实现,可能的触发点如下:
- MediaSession初始化延迟:你在
onCreate中先初始化ExoPlayer,再创建MediaSession。如果ExoPlayer初始化耗时过长(比如解码器加载、轨道选择器初始化阻塞),会导致Media3无法及时触发前台服务的通知绑定,超过系统时限。 - 音频属性适配问题:你设置的
AUDIO_CONTENT_TYPE_SPEECH类型,部分Android 13设备可能对语音类音频的前台服务判定逻辑特殊,导致Media3未自动触发前台通知。 - 后台启动场景限制:若服务是从后台场景触发(比如应用被杀死后通过耳机线控/蓝牙设备启动),Android 13的后台启动限制会让服务启动后处于受限状态,无法及时完成前台绑定。
- Media3版本bug:若使用的Media3版本较旧,可能存在Android 13前台服务适配漏洞,未正确处理
mediaPlayback类型的前台服务豁免逻辑。
2. 修复方案
- 调整初始化顺序:将MediaSession的创建提前到ExoPlayer初始化之前,确保Media3能及时接管前台服务逻辑:
override fun onCreate() { super.onCreate() // 先创建MediaSession mMediaSession = MediaSession.Builder(this, forwardingPlayer) .setId(System.currentTimeMillis().toString().takeLast(5)) .setCallback(librarySessionCallback).build() // 再初始化ExoPlayer initExoPlayer() } - 修改音频属性:将音频类型改为通用媒体类型,避免设备对语音类型的特殊处理:
val mAudioAttr = AudioAttributes.Builder() .setUsage(C.USAGE_MEDIA) .setContentType(C.AUDIO_CONTENT_TYPE_MUSIC) // 改为通用媒体类型 .build() - 升级Media3版本:更新至Media3最新稳定版(如1.2.0+),修复已知的Android 13适配问题。
- 绑定SessionActivity:通过
MediaSession.Builder.setSessionActivity()绑定一个合法的Activity,帮助系统识别合法的前台启动场景。
3. 复现崩溃的方法
- 后台触发服务启动:完全退出应用(划掉后台),通过耳机线控、蓝牙设备的播放按钮触发服务启动,此时Android 13的后台启动限制会放大服务初始化延迟的影响,容易触发超时崩溃。
- 模拟初始化耗时:在ExoPlayer初始化前添加
Thread.sleep(6000)模拟缓慢初始化,超过系统5秒时限触发崩溃。 - 禁用通知权限测试:手动禁用应用的通知权限后启动播放,部分Android 13设备会因Media3无法创建前台通知,导致服务无法完成前台绑定而崩溃。
内容的提问来源于stack exchange,提问作者BejanCorneliu
相关产品推荐
相关产品推荐

