You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android:如何基于MediaSession确定当前正在播放的音乐应用?

解决Android多MediaSession下判断当前播放应用的问题

你遇到的核心问题是会话切换时状态更新存在延迟,只靠OnActiveSessionsChangedListener的单次回调没法及时拿到最新的播放状态。正确的做法是结合「会话变化监听」+「每个会话的播放状态实时监听」,双管齐下:

1. 给每个MediaController注册PlaybackState回调

不要只在会话变化时一次性检查状态,而是给每个活跃的MediaController注册PlaybackStateCallback,这样无论何时播放状态变化(包括切换应用时的状态更新),你都能第一时间收到通知:

private val playbackStateCallback = object : MediaController.Callback() {
    override fun onPlaybackStateChanged(state: PlaybackState?) {
        super.onPlaybackStateChanged(state)
        // 当状态变为播放时,更新当前控制器
        if (state?.state == PlaybackState.STATE_PLAYING) {
            currentMediaController = this@YourClass.mMediaController
        }
        // 可选:如果状态变为暂停/停止,且当前控制器是它,重新检查活跃会话
        else if (state?.state in listOf(PlaybackState.STATE_PAUSED, PlaybackState.STATE_STOPPED) 
                 && currentMediaController == this@YourClass.mMediaController) {
            checkActivePlayingSession()
        }
    }

    override fun onMetadataChanged(metadata: MediaMetadata?) {
        super.onMetadataChanged(metadata)
        // 如果当前控制器是这个,同步更新歌曲信息
        if (currentMediaController == this@YourClass.mMediaController) {
            updateSongInfo(metadata)
        }
    }
}

2. 在会话变化时管理回调注册

在OnActiveSessionsChangedListener中,不仅要遍历检查当前状态,还要给新的会话注册回调,同时给移除的会话取消注册,避免内存泄漏:

// 维护旧会话列表,用于取消回调注册
private val oldControllers = mutableListOf<MediaController>()

private val mSessionsChangedListener = MediaSessionManager.OnActiveSessionsChangedListener { list ->
    list?.let { controllers ->
        // 取消旧会话的回调注册
        oldControllers.forEach { controller ->
            controller.unregisterCallback(playbackStateCallback)
        }
        // 更新旧会话列表
        oldControllers.clear()
        oldControllers.addAll(controllers)

        // 给新会话注册回调
        controllers.forEach { controller ->
            controller.registerCallback(playbackStateCallback)
        }

        // 初始检查当前正在播放的会话
        checkActivePlayingSession()
    }
}

// 辅助方法:遍历活跃会话找正在播放的
private fun checkActivePlayingSession() {
    currentMediaController = oldControllers.firstOrNull {
        it.playbackState?.state == PlaybackState.STATE_PLAYING
    }
    // 如果找到,直接更新歌曲信息
    currentMediaController?.let {
        updateSongInfo(it.metadata)
    }
}

3. 额外注意事项

  • 权限方面:Android 12及以下需申请android.permission.MEDIA_CONTENT_CONTROL,Android 13+需申请android.permission.READ_MEDIA_PLAYBACK_STATE,否则无法获取会话信息。
  • 部分媒体应用切换时会先暂停旧会话、再启动新会话,这时onPlaybackStateChanged会触发两次,你的回调能准确捕捉到状态变化。

内容的提问来源于stack exchange,提问作者Ziad Halabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:13:37