首先是客户端代,我们需要做的是建立连接,并且在连接成功后设置回调,客户端再Activity中实现:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
...
//媒体浏览器
private MediaBrowser mMediaBrowser;
//媒体控制器
private MediaController mMediaController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//新建MediaBrowser,第一个参数是context
//第二个参数是CompoentName,有多种构造方法,指向要连接的服务
//第三个参数是连接结果的回调connectionCallback,第四个参数为Bundle
mMediaBrowser = new MediaBrowser(this,
new ComponentName(this, MediaService.class), connectionCallback, null);
mMediaBrowser.connect();
...
}
//连接结果的回调
private MediaBrowser.ConnectionCallback connectionCallback
= new MediaBrowser.ConnectionCallback() {
public void onConnected() {
//如果服务端接受连接,就会调此方法表示连接成功,否则回调onConnectionFailed();
Log.d(TAG, "onConnected: ");
//获取配对令牌
MediaSession.Token token = mMediaBrowser.getSessionToken();
//通过token,获取MediaController,第一个参数是context,第二个参数为token
mMediaController = new MediaController(getBaseContext(), token);
//mediaController注册回调,callback就是媒体信息改变后,服务给客户端的回调
mMediaController.registerCallback(mMediaCallBack);
}
public void onConnectionSuspended() {
//与服务断开回调(可选)
}
public void onConnectionFailed() {
//连接失败回调(可选)
}
}
//服务对客户端的信息回调。
private MediaController.Callback mMediaCallBack = new MediaController.Callback() {
//回调函数的方法都是选择性重写的,这里不列举全,具体可查询文章末尾的表格
@Override
public void onMetadataChanged(MediaMetadata metadata) {
super.onMetadataChanged(metadata);
//服务端运行mediaSession.setMetadata(mediaMetadata)就会到达此处,以下类推.
//歌曲信息回调,更新。MediaMetadata在文章后面会提及
MediaDescription description = metadata.getDescription();
//获取标题
String title = description.getTitle().toString();
//获取作者
String author = description.getSubtitle().toString();
//获取专辑名
String album = description.getDescription().toString();
//获取总时长
long duratime = mediaMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
...
}
@Override
public void onPlaybackStateChanged(PlaybackState state) {
super.onPlaybackStateChanged(state);
//播放状态信息回调,更新。PlaybackState在文章后面会提及
if (state.getState() == PlaybackState.STATE_PLAYING) {
//正在播放
}
...
//获取当前播放进度
long position = state.getPosition()
....
}
@Override
public void onQueueChanged(List<MediaSession.QueueItem> queue) {
super.onQueueChanged(queue);
//播放列表信息回调,QueueItem在文章后面会提及
....
}
@Override
public void onSessionEvent(String event, Bundle extras) {
super.onSessionEvent(event, extras);
//自定义的事件回调,满足你各种自定义需求
...
}
@Override
public void onExtrasChanged(Bundle extras) {
super.onExtrasChanged(extras);
//额外信息回调,可以承载播放模式等信息
}
.....
}
}
接下来看服务端,我们要做的是同意客户端连接,响应客户端的控制命令,并且在信息改变时通知回调给客户端,服务端再Service中实现:
public class MediaService extends MediaBrowserService{
...
//媒体会话,受控端
private MediaSession mediaSession;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
//初始化,第一个参数为context,第二个参数为String类型tag,这里就设置为类名了
mediaSession = new MediaSession(this, "MediaService");
//设置token
setSessionToken(mediaSession.getSessionToken());
//设置callback,这里的callback就是客户端对服务指令到达处
mediaSession.setCallback(mCallback);
}
//mediaSession设置的callback,也是客户端控制指令所到达处
private MediaSession.Callback mCallback = new MediaSession.Callback() {
//重写的方法都是选择性重写的,不完全列列举,具体可以查询文章末尾表格
@Override
public void onPlay() {
super.onPlay();
//客户端mMediaController.getTransportControls().play()就会调用到这里,以下类推
//处理播放逻辑
...
//处理完成后通知客户端更新,这里就会回调给客户端的MediaController.Callback
mediaSession.setPlaybackState(playbackState);
}
@Override
public void onPause() {
super.onPause();
//暂停
....
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
//下一首
.....
//通知媒体信息改变
mediaSession.setMetadata(mediaMetadata);
}
@Override
public void onCustomAction(String action, Bundle extras) {
super.onCustomAction(action, extras);
//自定义指令发送到的地方
//对应客户端 mMediaController.getTransportControls().sendCustomAction(...)
}
....
}
//自己写的方法,用于改变播放列表
private void changePlayList(){
....
//通知播放队列改变
mediaSession.setQueue(queueItems);
}
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
//MediaBrowserService必须重写的方法,第一个参数为客户端的packageName,第二个参数为Uid
//第三个参数是从客户端传递过来的Bundle。
//通过以上参数来进行判断,若同意连接,则返回BrowserRoot对象,否则返回null;
//构造BrowserRoot的第一个参数为rootId(自定义),第二个参数为Bundle;
return new BrowserRoot("MyMedia", null);
}
@Override
public void onLoadChildren(String parentId,
MediaBrowserService.Result<List<MediaBrowser.MediaItem>> result) {
//MediaBrowserService必须重写的方法,用于处理订阅信息,文章后面会提及
....
}
....
}
在客户端与服务端建立连接后,就可以调用mMediaController的播放、暂停、上下首、跳转某个时间点方法了,如:在客户端Activity的播放按键onClick回调时调用mMediaController.getTransportControls().play(),这时在服务端的MediaSession.Callback() 的onPlay()方法就会被调用,我们可以在onPlay方法中调用MediaPlay的start方法。