一、MediaSession:跨设备媒体控制的 “中央枢纽”
一句话理解:MediaSession 是 Android 系统为媒体应用提供的 “智能管家”,它统一管理播放状态(如播放 / 暂停)、接收跨设备控制指令(如耳机、车载系统),并将信息同步到通知栏、锁屏等界面。
🌰 生活类比:家庭智能音响的遥控器
-
你在家用手机播放音乐,此时:
- 手机屏幕、智能手表、蓝牙音箱按钮都能控制暂停 —— 这相当于 MediaController 发送指令;
- 音响内部记录 “当前播放第 3 首歌、进度 50%”—— 这是 MediaSession 管理的状态;
- 音响后台持续运行并提供歌曲列表 —— 这是 MediaBrowserService 在工作。
二、Media 框架核心组件:四大角色分工
1. MediaSession(媒体会话):状态管理中枢
-
核心职责:
- 存储播放状态(播放中 / 暂停)、媒体信息(歌名、封面、进度);
- 接收控制指令(播放 / 暂停 / 切歌),并通知播放器执行;
- 同步状态到系统(如通知栏、锁屏界面)。
-
关键代码示例:
kotlin
// 初始化 MediaSession mediaSession = MediaSessionCompat(this, "MusicApp") // 设置媒体信息(如歌曲封面、标题) mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "七里香") .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt) .build() ) // 设置播放状态(播放中,进度15秒) mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_PLAYING, 15000, 1.0f) .build() )
2. MediaBrowserService(媒体服务):数据与播放器的持有者
-
核心职责:
- 运行在后台,持有播放器实例(如 ExoPlayer);
- 向其他应用提供媒体数据(如歌曲列表、专辑信息);
- 连接 MediaSession,处理跨进程控制请求。
-
典型场景:
当车载系统需要获取手机音乐列表时,通过 MediaBrowser 连接到音乐 App 的 MediaBrowserService,服务通过onLoadChildren
方法返回歌曲数据。
3. MediaBrowser(媒体浏览器):客户端的连接工具
-
核心职责:
- 作为客户端(如手机 UI、车载系统)的 “连接器”,连接到后台的 MediaBrowserService;
- 获取媒体数据(歌曲列表),并监听服务状态变化。
-
代码示例:
kotlin
// 连接后台服务 mediaBrowser = MediaBrowserCompat( context, ComponentName(context, MusicService::class.java), connectionCallback, null ) mediaBrowser.connect() // 建立连接
4. MediaController(媒体控制器):指令发送器
-
核心职责:
- 作为 “遥控器”,向 MediaSession 发送控制指令(播放 / 暂停 / 切歌);
- 获取 MediaSession 的状态,更新 UI(如按钮状态、进度条)。
三、MediaSession 工作流程:从初始化到跨设备控制
-
初始化阶段
- 服务端(MediaBrowserService)创建 MediaSession,并绑定播放器;
- 客户端(MediaBrowser)连接服务,获取 MediaController。
-
状态同步
- 服务端通过
setMetadata
和setPlaybackState
更新媒体信息和播放状态; - 系统自动将状态同步到通知栏、锁屏(需配置
MediaStyle
通知)。
- 服务端通过
-
跨设备控制
- 外部设备(如蓝牙耳机)发送控制指令(如暂停);
- 指令通过系统传递给 MediaSession,再由 MediaSession 通知播放器执行。
四、实战:MediaSession 与 ExoPlayer 结合
kotlin
class MusicService : MediaBrowserServiceCompat() {
private lateinit var exoPlayer: ExoPlayer
private lateinit var mediaSession: MediaSessionCompat
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 初始化 ExoPlayer
exoPlayer = ExoPlayer.Builder(this).build()
// 初始化 MediaSession
mediaSession = MediaSessionCompat(this, "MusicService")
mediaSession.setCallback(object : MediaSessionCompat.Callback() {
override fun onPlay() {
exoPlayer.play() // 播放
updatePlaybackState() // 更新状态
}
override fun onPause() {
exoPlayer.pause() // 暂停
updatePlaybackState()
}
})
mediaSession.isActive = true // 激活会话
return START_STICKY // 服务被杀死后尝试重启
}
private fun updatePlaybackState() {
val state = if (exoPlayer.isPlaying) {
PlaybackStateCompat.STATE_PLAYING
} else {
PlaybackStateCompat.STATE_PAUSED
}
mediaSession.setPlaybackState(
PlaybackStateCompat.Builder()
.setState(state, exoPlayer.currentPosition, 1.0f)
.build()
)
}
}
五、核心场景与最佳实践
-
通知栏集成
-
使用
MediaStyle
通知,自动显示 MediaSession 的状态:kotlin
val notification = NotificationCompat.Builder(this, channelId) .setStyle(androidx.media.app.NotificationCompat.MediaStyle() .setMediaSession(mediaSession.sessionToken)) .build() startForeground(1, notification)
-
-
音频焦点与 MediaSession 协同
-
当应用失去音频焦点时(如来电),MediaSession 应暂停播放:
kotlin
when (focusChange) { AudioManager.AUDIOFOCUS_LOSS -> { mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_PAUSED, ...) .build() ) exoPlayer.pause() } }
-
-
Android 12+ 适配
-
新增
MediaController2
和MediaSession2
,支持更灵活的跨设备控制(如多设备音频路由):kotlin
// 创建 MediaSession2 val mediaSession2 = MediaSession2.Builder(context, "MusicApp") .setPlaybackProperties(PlaybackProperties.Builder() .setSupportedActions(PlaybackState.ACTION_PLAY | ACTION_SKIP_TO_NEXT) .build()) .build()
-
六、常见问题与解决方案
-
问题:通知栏控制按钮无响应
- 原因:MediaSession 未正确绑定控制器
- 方案:确保
MediaStyle
通知关联了 MediaSession 的sessionToken
-
问题:跨设备控制延迟
- 原因:服务连接超时或状态更新不及时
- 方案:使用
MediaBrowserCompat
的onServiceConnected
回调确保连接成功后再发送指令
-
问题:后台服务被系统杀死
- 方案:使用
START_STICKY
模式,并通过setForegroundServiceType
声明媒体播放类型
- 方案:使用
七、总结
MediaSession 与 Media 框架是 Android 媒体开发的核心基础设施,其核心价值在于:
-
统一控制:让手机、耳机、车载等设备都能无缝操作播放器;
-
状态同步:自动更新通知栏、锁屏等系统界面;
-
后台持久化:支持应用在后台稳定运行并响应控制。
掌握这套框架,不仅能开发音乐、视频类应用,还能为智能家居、车载系统等跨设备场景提供媒体控制能力。