Android 13移除最近应用后MediaSessionService被销毁问题求助
问题描述
我在Activity的onCreate中启动服务:Android Oreo及以上版本使用startForegroundService,更低版本使用startService。在服务中,我通过通知工具类调用startForeground方法。应用处于前台时播放器运行正常且显示通知,但一旦将应用从最近应用列表移除,服务就会被销毁——该服务本应作为前台服务持续运行,不清楚停止的原因。
尝试过的解决方案:在Oreo及以上版本改用startService启动,还有其他方法;最后一种是服务销毁后重启,虽能工作但并不理想。
测试环境:Android 13
Activity代码
class MainActivity : ComponentActivity() { private var isServiceRunning: Boolean = false private fun startingService(){ if (!isServiceRunning){ var intent = Intent(this, PlaybackSessionService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ startForegroundService(intent) }else{ startService(intent) } isServiceRunning = true } } @OptIn(UnstableApi::class) override fun onCreate(savedInstanceState: Bundle?) { startingService() //the rest code compose Ui }
PlaybackSessionService代码
class PlaybackSessionService: MediaSessionService() { val mediaSession: MediaSession by inject() val musiCoNotificationManager: MusiCoNotificationManager by inject() @OptIn(UnstableApi::class) override fun onCreate() { super.onCreate() Log.e("ks","onCreate service") musiCoNotificationManager.startNotificationService( mediaSession = mediaSession, mediaSessionService = this ) } @OptIn(UnstableApi::class) override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.e("ks","onStartCommand service") musiCoNotificationManager.startNotificationService( mediaSession = mediaSession, mediaSessionService = this ) return super.onStartCommand(intent, flags, startId) } override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? { return mediaSession } override fun onTaskRemoved(rootIntent: Intent?) { super.onTaskRemoved(rootIntent) } override fun onDestroy() { super.onDestroy() Log.e("ks","Service destroyed") mediaSession.apply { release() if (player.playbackState != Player.STATE_IDLE){ player.seekTo(0) player.playWhenReady = false player.stop() player.release() } } } }
NotificationManager代码
class MusiCoNotificationManager( private val context: Context, private val player: ExoPlayer, ): KoinComponent { @UnstableApi fun startNotificationService( mediaSessionService: MediaSessionService, mediaSession: MediaSession ){ buildNotification(mediaSession) startForegroundNotificationService(mediaSessionService) } private fun startForegroundNotificationService(mediaSessionService: MediaSessionService){ Log.e("ks","Enter startForeground fun in MusiCoNotificationManager class ") val notification = NotificationCompat.Builder(context, MusicoApp.NOTIFICATION_CHANNEL_ID) .setOngoing(true) .setOnlyAlertOnce(true) .build() mediaSessionService.startForeground(MusicoApp.NOTIFICATION_ID,notification) } @UnstableApi private fun buildNotification(mediaSession: MediaSession){ PlayerNotificationManager.Builder( context, MusicoApp.NOTIFICATION_ID, MusicoApp.NOTIFICATION_CHANNEL_ID ) .setMediaDescriptionAdapter( MusiCoNotificationAdapter(context = context, pendingIntent = mediaSession.sessionActivity) ) .setSmallIconResourceId(R.drawable.music_note) .build() .also { it.setMediaSessionToken(mediaSession.platformToken) it.setUseFastForwardActionInCompactView(true) it.setUseNextActionInCompactView(true) it.setUseRewindActionInCompactView(true) it.setUsePreviousActionInCompactView(true) it.setPriority(NotificationCompat.PRIORITY_DEFAULT) it.setPlayer(player) } } }
问题原因与解决办法
1. onStartCommand返回值错误
你的onStartCommand返回了父类默认值START_NOT_STICKY,该值意味着系统杀死服务后不会自动重启,且应用从最近列表移除时,服务会被直接终止。
修复:将返回值改为START_STICKY或START_REDELIVER_INTENT:
START_STICKY:系统重启服务后传入空Intent,适合无需恢复播放状态的场景START_REDELIVER_INTENT:系统会重新传递最后一次的Intent,适合需要恢复播放进度的场景
修改后的代码:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.e("ks","onStartCommand service") musiCoNotificationManager.startNotificationService( mediaSession = mediaSession, mediaSessionService = this ) return START_STICKY // 或START_REDELIVER_INTENT }
2. 通知冲突导致前台服务失效
你同时使用PlayerNotificationManager和手动调用startForeground,两者共用同一个NOTIFICATION_ID,会导致通知被覆盖,系统可能判定前台服务的通知无效,进而杀死服务。
修复:让PlayerNotificationManager自动处理前台服务逻辑,移除手动调用startForeground的代码:
修改MusiCoNotificationManager的startNotificationService方法:
@UnstableApi fun startNotificationService( mediaSessionService: MediaSessionService, mediaSession: MediaSession ){ // PlayerNotificationManager内部会自动调用startForeground buildNotification(mediaSession) }
3. 额外配置检查
- Android 13通知权限:确保已在Manifest中声明权限,并在运行时申请:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
- 服务声明配置:Android 12+需在Manifest中指定
foregroundServiceType:
<service android:name=".PlaybackSessionService" android:foregroundServiceType="mediaPlayback" android:exported="true"> <intent-filter> <action android:name="android.media.browse.MediaBrowserService" /> </intent-filter> </service>
onTaskRemoved处理:保持当前空实现,不要调用stopSelf(),避免应用从最近列表移除时主动终止服务。
内容的提问来源于stack exchange,提问作者Khalid Ahmed
相关产品推荐
相关产品推荐

