mSession.setPlaybackState(mStateBuilder.build());
// 5. 关联 SessionToken
setSessionToken(mSession.getSessionToken());
}
}
根据包名做权限判断之后,返回根路径
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
// 根据包名对每个访问端做一些访问权限判断等
}
用来根据mediaID来返回第三放App所需要获得媒体数据
@Override
public void onLoadChildren(final String parentMediaId,
final Result<List> result) {
// 根据parentMediaId返回播放列表相关信息
}
客户端连接
private void initMediaBrowser() {
//1.待连接的服务
ComponentName componentName = new ComponentName(“com.example.android.uamp”,“com.example.android.uamp.MusicService”);
//2.创建MediaBrowser
mMediaBrowser = new MediaBrowserCompat(this, componentName, mConnectionCallbacks, null);
//3.建立连接
mMediaBrowser.connect();
}
设置相应的callback,连接Callback,数据变化Callback
连接状态同步
数据变化Callback设置
private final MediaBrowserCompat.ConnectionCallback mConnectionCallbacks =
new MediaBrowserCompat.ConnectionCallback() {
@Override
public void onConnected() {
//连接成功回调
}
@Override
public void onConnectionSuspended() {
//连接中断回调
}
@Override
public void onConnectionFailed() {
//连接失败回调
}
};
MediaControllerCompat.Callback controllerCallback =
new MediaControllerCompat.Callback() {
public void onSessionDestroyed() {
//Session销毁
}
@Override
public void onRepeatModeChanged(int repeatMode) {
//循环模式发生变化
}
@Override
public void onShuffleModeChanged(int shuffleMode) {
//随机模式发生变化
}
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
//数据变化
}
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
//播放状态变化
}
};
客户端与服务端数据交互
MediaBrowser通过调用subscribe,会回调到MediaService的onLoadChildren,在这里做一个判断然后构造相应的列表将列表数据返回。返回数据之后。
- 根据MediaID获取数据
客户端通过调用subscribe方法,传递MediaID,在SubscriptionCallback的方法中进行处理。
mMediaBrowser.subscribe(“ID”, new MediaBrowserCompat.SubscriptionCallback() {
@Override
public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaBrowserCompat.MediaItem> children) {
//children 为来自Service的列表数据
}
});
服务端和客户端之间传递的数据为MediaItem列表。MediaItem中具备的字段:MediaId,Title,SubTitle,Description,Icon,IconUri,MediaUri等字段。通过其可以帮助我们携带一些数据来进行歌曲的展示和播放。
@Override
public void onLoadChildren(@NonNull final String parentMediaId,
@NonNull final Result<List> result) {
List items = new ArrayList<>();
//根据MediaID做数据填充
switch (parent
MediaId) {
case:
default: break;
}
result.sendResult(items);
}
- 发送自定义数据获取内容
客户端通过调用sendCustomAction,根据与服务端的协商,制定相应的action类型,进行数据的传递交互。
mMediaBrowser.sendCustomAction(action, extras, new MediaBrowserCompat.CustomActionCallback() {
@Override
public void onProgressUpdate(String action, Bundle extras, Bundle data) {
super.onProgressUpdate(action, extras, data);
}
@Override
public void onResult(String action, Bundle extras, Bundle resultData) {
super.onResult(action, extras, resultData);
}
@Override
public void onError(String action, Bundle extras, Bundle data) {
super.onError(action, extras, data);
}
});
服务端实现onCustomAction,根据action类型返回相应的数据
@Override
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result result) {
//分支判断
if (GET_LIST.equals(action)) {
Bundle bundle = new Bundle();
ArrayList list = new ArrayList<>();
//填充数据
bundle.putStringArrayList(LIST_NAMES, list);
result.sendResult(bundle);
}
}
播放控制
- 客户端
客户端通过getMediaController getTransportControls()来进行播放,暂停,上一首,下一首的控制。
//获取播放状态
int pbState = MediaControllerCompat.getMediaController(MainActivity.this).getPlaybackState().getState();
//根据播放状态进行播放控制
if (pbState == PlaybackStateCompat.STATE_PLAYING) {
MediaControllerCompat.getMediaController(MainActivity.this).getTransportControls().pause();
} else {
MediaControllerCompat.getMediaController(MainActivity.this).getTransportControls().play();
}
- 服务端
在服务端为MediaSession设置SessionCallback,来实现相应的播放功能。
mSession.setCallback(mSessionCallback);
客户端通过MediaController可以进行播放,暂停,根据MediaID播放下一个音乐,音乐播放快进等。所有的操作会回调到服务端的MediaSessionCallback的play,seekTo等方法,需要我们自己实现,在其中控制播放队列,然后根据列表播放的情况来动态的变更队列。
播放状态同步
对于播放状态的同步,比如当前播放到哪一个歌曲,当前是暂停还是播放中。客户端通过Controller回调就可以得到相应的变化,但是,变化状态,服务端如何发送呢?
setMetadata(android.media.MediaMetadata));
setPlaybackState(android.media.session.PlaybackState));
设置当前的歌曲信息,设置当前的播放状态。设置之后,客户端将会得到更新。
获取手机内的媒体服务
private void discoverBrowseableMediaApps(Context context) {
PackageManager packageManager = context.getPackageManager();
Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
List services = packageManager.queryIntentServices(intent, 0);
for (ResolveInfo resolveInfo : services) {
if (resolveInfo.serviceInfo != null && resolveInfo.serviceInfo.applicationInfo != null) {
ApplicationInfo applicationInfo = resolveInfo.serviceInfo.applicationInfo;
String label = (String) packageManager.getApplicationLabel(applicationInfo);
Drawable icon = packageManager.getApplicationIcon(applicationInfo);
String className = resolveInfo.serviceInfo.name;
String packageName = resolveInfo.serviceInfo.packageName;
MusicService service = new MusicService();
service.icon = icon;
service.lable = label;
service.className = className;
service.packageName = packageName;
musicServiceList.add(service);
}
}
}
结语
通过本篇文章,对MediaBroswerService做了一个简单的介绍,但对于播放器的具体实现,特别是在服务端还是比较复杂的,需要维护歌曲队列,进行播放,同时负责状态的更新。
最后,小编这里放上自己整理的Android学习思维脑图及架构资料。
资料领取
点赞+加群免费获取 Android IOC架构设计
加群领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-uyDfPFGj-1718987439150)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
id工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助**。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-uyDfPFGj-1718987439150)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取