从最近的应用程序中删除应用程序后,MediaSessionService 被销毁

问题描述 投票:0回答:1

我在 Activity 的 onCreate 中启动服务,对于 Android Oreo 及以上版本使用 startForegroundService,对于较低版本则使用 startService,在服务中,我通过调用通知辅助方法在 Service 中使用 startForeground,当应用程序位于前台时,播放器可以完美工作,显示通知,但是一旦我从最近的应用程序中删除该应用程序,该服务就会被销毁。该服务应该继续作为前台服务工作,但我不知道为什么它一直停止

我尝试了一些解决方案,例如 Oreo 及以上版本的 startService 而不是 startForegroundService,我尝试了其他解决方案,最后一个解决方案是在服务被破坏后重新启动服务,但它可以工作,但并不理想。 我正在 Anroid 13 中测试该应用程序


这是我的活动

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

这是我的通知管理器

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


}
android kotlin exoplayer foreground-service android-media3
1个回答
0
投票

我解决了这个问题,只是我需要 MediaController 将其与 MediaSessionService 连接,并且使用 MediaController 你不需要从 Activity 启动ForegroundService,也不需要在服务内启动Foreground,你只需要 MediaController,前台通知由MediaSessionService 正如 documentation 所说,如果您愿意,您可以制作自定义的服务,但如果您自己发出通知,我不确定您是否需要将服务作为前台启动活动。

这是样本 在 onStart 的 Activity 中

    override fun onStart() {
        super.onStart()
        val sessionToken = SessionToken(this, ComponentName(this,
            PlayerSessionService::class.java))

        val controllerFuture = MediaController.Builder(this,sessionToken).buildAsync()
        controllerFuture.addListener({
            if (controllerFuture.isDone){
                controller = controllerFuture.get()
            }
        }, MoreExecutors.directExecutor()
        )

    }

就这个

注意: 你不能使用像 koin 或 dagger hilt 这样的 di 注入 MediaController 当我尝试使用 koin 注入它时遇到问题,这会冻结我的应用程序,原因是 MediaController 需要几秒钟才能初始化

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.