MediaSession主要解决了什么问题?
早期多媒体应用的控制逻辑与播放逻辑紧密耦合,处于同一个进程中。
随着多媒体用户场景的拓展,用户能够在锁屏页、通知栏、桌面widget、蓝牙耳机、遥控器等地方来控制媒体播放、查看媒体信息。这些场景下媒体的信息展示、播放控制和播放实现处于不同的进程下,这需要我们在技术上将媒体控制逻与媒体播放实现解耦合,提升应用的灵活性和扩展性。
MediaSession就是为了解耦媒体控制与播放逻辑而生的,它是Android系统提供的一种实现媒体控制与播放实现分离的框架;利用MediaSession框架,我们能够将自己App的媒体播放能力(可以认为是媒体服务端)发布到系统中,供系统和其他进程调用,我们也可以使用MediaSession提供的标准化API来控制已经接MediaSession框架的App或者系统媒体服务,并且可以通过标准化API自动同步播放状态和播放视频的信息。
总结下:
- MediaSession是一种媒体控制与播放实现分离的框架
- MediaSession提供了标准化的媒体控制、播放状态管理和同步方案
MediaSession是如何解决这些问题的?
先上图~
MediaSession 框架提供了一套标准化的 API:
开发者调用MediaController 标准的媒体控制API时候,MediaSession 框架会把媒体控制命令(可跨进程)转发给MediaSession服务端,开发者需要在MediaSession服务端的回调接口中调用播放器对应的播放、暂停等方法;同时开发者也需要在播放状态变化的时候,通过MediaSession 将服务端播放器的各种播放状态(播放、暂停、退出)和视频信息跨进程通知到MediaController 。
开发者调用MediaBrower的获取媒体文件列表、获取文件信息等标准API时候,MediaSession 框架会把浏览命令(可跨进程)转发MediaBrowerService,开发者需要在自定义的MediaBrowerService中实现获取媒体文件目录以及单个媒体信息的方法,MediaSession 框架也会把这些目录和媒体信息跨进程发送给MediaBrower实例,需要注意一点是,MediaBrower实现前提是媒体文件的组织结构类似于树状结构。
MediaSession 使用示例
下面是一个在 Android 中使用 MediaSession
的代码示例:
1. 创建 MediaSession
import android.content.Context;
import android.media.MediaPlayer;
import android.media.session.MediaSession;
import android.media.session.MediaSession.Callback;
import android.media.session.MediaSession.Token;
import androidx.media.session.MediaControllerCompat;
import androidx.media.session.MediaMetadataCompat;
public class MyMediaService extends Service {
private MediaSession mediaSession;
private MediaPlayer mediaPlayer;
@Override
public void onCreate() {
super.onCreate();
// 初始化 MediaPlayer
mediaPlayer = new MediaPlayer();
// 创建 MediaSession
mediaSession = new MediaSession(this, "MyMediaSession");
// 设置回调,处理媒体控制命令
mediaSession.setCallback(new Callback() {
@Override
public void onPlay() {
mediaPlayer.start(); // 开始播放
mediaSession.setActive(true); // 激活 MediaSession
}
@Override
public void onPause() {
mediaPlayer.pause(); // 暂停播放
}
@Override
public void onStop() {
mediaPlayer.stop(); // 停止播放
mediaSession.release(); // 释放 MediaSession
}
});
// 设置媒体元数据
MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, "Sample Title")
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, "Sample Artist")
.build();
mediaSession.setMetadata(metadata); // 设置元数据
// 启动 MediaSession
mediaSession.setActive(true); // 激活 MediaSession
}
@Override
public IBinder onBind(Intent intent) {
return null; // 返回 null 表示不绑定
}
@Override
public void onDestroy() {
super.onDestroy();
mediaSession.release(); // 释放 MediaSession
mediaPlayer.release(); // 释放 MediaPlayer
}
}
2. 使用 MediaController 控制 MediaSession
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
// 在其他组件中控制 MediaSession
public void controlMediaSession(Context context) {
MediaSessionManager mediaSessionManager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
MediaController mediaController = null;
// 获取正在运行的 MediaSession
for (MediaController controller : mediaSessionManager.getActiveSessions(new ComponentName(context, MyMediaService.class))) {
mediaController = controller; // 获取第一个 MediaController
break;
}
if (mediaController != null) {
// 控制命令
mediaController.getTransportControls().play(); // 播放
mediaController.getTransportControls().pause(); // 暂停
mediaController.getTransportControls().stop(); // 停止
}
}
未来媒体框架的演进
随着技术的不断发展,未来的媒体框架可能会在以下几个方面演进:
- 增强的跨平台支持:随着不同设备(如智能音箱、车载系统等)的普及,未来的媒体框架可能会进一步增强跨平台的支持能力,使得开发者能够更方便地为多种设备提供一致的媒体控制体验。
-
更丰富的元数据支持:未来的
MediaSession
可能会扩展对更丰富元数据的支持,例如支持更复杂的内容类型、动态生成的封面等,以提升用户的多媒体体验。 - 智能控制功能:随着 AI 和机器学习技术的发展,未来的媒体框架可能会引入智能控制功能,能够根据用户的习惯和偏好自动调整播放设置,提供个性化的媒体体验。
- 增强的隐私和安全性:随着对用户隐私的重视,未来的媒体框架可能会加强对用户数据的保护,确保在媒体控制和共享过程中保持用户的隐私。