今天说的这个主题与媒体播放有关,尤其是音乐播放,说到音乐播放大家应该都用过音乐App。
通常一个音乐App的实现主要涉及如下几点:
1. 从服务器获取音乐数据
2. 播放音乐时播放器的各种播放状态以及不同状态下的UI展示
3. 播放过程中通过UI界面控制播放器的各种状态
4. UI控制如何与播放服务进行关联并进行状态同步
4. 如何保证后台播放过程中播放服务不被杀死

对于上面的这几点,其实Android已经为我们提供了一套完整的解决方案,它已经很好的将这些操作进行了封装,我们只需要关注数据的获取和歌曲的播放即可。Android提供的这套API在support-v4中提供了兼容版本,因此在使用的过程中最好使用该版本以兼容低版本系统。

关键类主要有如下几个:
1. MediaBrowserServiceCompat 媒体浏览器服务
2. MediaBrowserCompat 媒体浏览器
2. MediaControllerCompat 媒体控制器
3. MediaSessionCompat 媒体会话
我们一个个来说。

MediaBrowserServiceCompat

该类有两个作用:
1. 音乐播放后台服务
2. 客户端中获取音乐数据的服务,所有的音乐数据都通过该服务与服务端进行交互获取(或者直接获取手机中的本地音乐数据)

既然知道该类是Service的子类实现,所以说它是音乐播放的后台服务也好理解,但是该类作为一个后台播放服务却不是通过其自身直接实现的,而是通过MediaSessionCompat媒体会话这个类来实现的。在使用过程中媒体会话会与该服务关联起来,所有的播放操作都交由MediaSessionCompat实现。

而对于获取数据,则是通过MediaBrowserServiceCompat的如下两个方法来进行控制:

@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid,Bundle rootHints) {/*** 在返回数据之前,可以进行黑白名单控制,以控制不同客户端浏览不同的媒体资源* */if(!PackageUtil.isCallerAllowed(this, clientPackageName, clientUid)) {return new BrowserRoot(null, null);}//此方法只在服务连接的时候调用//返回一个rootId不为空的BrowserRoot则表示客户端可以连接服务,也可以浏览其媒体资源//如果返回null则表示客户端不能流量媒体资源return new BrowserRoot(BrowserRootId.MEDIA_ID_ROOT, null);
}@Override
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaItem>> result) {/**** 此方法中的parentId与上面的方法onGetRoot中返回的RootId没有关系* 客户端连接后,它可以通过重复调用MediaBrowserCompat.subscribe() 方法来发起数据获取请求。* 而每次调用subscribe() 方法都会发送一个onLoadChildren()回调到该service中,然后返回一个MediaBrowser.MediaItem(音乐数据) 对象列表** 每个MediaItem 都有唯一的ID字符串,它其实是一个隐式的token。* 当客户想打开子菜单或播放一个item时,它就将ID传入。*/if(BrowserRootId.MEDIA_ID_MUSIC_LIST_REFRESH.equals(parentId)) {//在当前方法执行结束返回之前必须要调用result.detach(),否则无法发起请求result.detach();MusicProvider.getInstance().requestMusic(result);//如果想要通过http请求来获取数据,则必须按照上面说的必须要先调用result.detach();方法,否则会出现异常。http请求结束之后则通过调用result.sendResult(mMetadataCompatList);将数据返回,返回的数据在注册的接口MediaBrowserCompat.SubscriptionCallback中通过回调拿到在界面上进行展示//而且此处返回的数据类型必须是MediaBrowser.MediaItem} else {result.detach();}
}

MediaBrowserCompat

前面说过MediaBrowserServiceCompat(媒体浏览服务)是作为数据请求服务来获取数据的,因此相应的会有一个媒体浏览客户端来发起媒体数据的获取请求,该类就是这个客户端。
前面已经介绍过通过调用MediaBrowserCompat.subscribe()方法来发起数据请求,而在调用此方法之前,必须保证MediaBrowserCompat连接上媒体浏览服务,连接方式如下:

//通过如下代码连接MediaBrowserServiceCompat,连接成功后获取媒体会话token
//通过媒体会话token创建MediaControllerCompat
//这时就将MediaControllerCompat与媒体会话MediaSessionCompat关联起来了
MediaBrowserCompat mediaBrowser = new MediaBrowserCompat(this,new ComponentName(this, MusicService.class), mConnectionCallback, null);//连接媒体浏览服务成功后的回调接口
final MediaBrowserCompat.ConnectionCallback mConnectionCallback =new MediaBrowserCompat.ConnectionCallback() {@Overridepublic void onConnected() {try {//获取与MediaBrowserServiceCompat关联的媒体会话tokenMediaSessionCompat.Token token = mMediaBrowser.getSessionToken();//通过媒体会话token创建媒体控制器并与之关联//关联之后媒体控制器就可以控制播放器的各种播放状态了MediaControllerCompat mediaController = new MediaControllerCompat(this, token);//将媒体控制器与当前上下文Context进行关联//此处关联之后,我们在界面上操作某些UI的时候就可以通过当前上下文Context来获取当前的MediaControllerCompat//MediaControllerCompat controller = MediaControllerCompat.getMediaController((Activity) context);MediaControllerCompat.setMediaController(this, mediaController);//为媒体控制器注册回调接口          mediaController.registerCallback(mMediaControllerCallback);} catch (RemoteException e) {onMediaControllerConnectedFailed();}}};//媒体控制器控制播放过程中的回调接口
final MediaControllerCompat.Callback mMediaControllerCallback =new MediaControllerCompat.Callback() {@Overridepublic void onPlaybackStateChanged(@NonNull PlaybackStateCompat state) {//播放状态发生改变时的回调onMediaPlayStateChanged(state);}@Overridepublic void onMetadataChanged(MediaMetadataCompat metadata) {if(metadata == null) {return;}//播放的媒体数据发生变化时的回调onPlayMetadataChanged(metadata);}};//发起数据请求//先解除订阅mediaBrowser.unsubscribe(BrowserRootId.MEDIA_ID_MUSIC_LIST_REFRESH);//重新对BrowserRootId进行订阅//调用此方法后,会接着执行MusicService中的onGetRoot方法和onLoadChildren方法//onGetRoot方法(只会调用一次)决定是否允许当前客户端连接服务和获取媒体数据//如果允许连接服务同时也允许获取媒体数据,则会接着调用onLoadChildren方法开始获取数据//数据获取成功后会调用订阅的回调接口将数据返回回来mediaBrowser.subscribe(BrowserRootId.MEDIA_ID_MUSIC_LIST_REFRESH, mSubscriptionCallback);//向媒体流量服务发起媒体浏览请求的回调接口
final MediaBrowserCompat.SubscriptionCallback mSubscriptionCallback =new MediaBrowserCompat.SubscriptionCallback() {@Overridepublic void onChildrenLoaded(@NonNull String parentId,@NonNull List<MediaBrowserCompat.MediaItem> children) {//数据获取成功后的回调}@Overridepublic void onError(@NonNull String id) {//数据获取失败的回调}};

MediaSessionCompat

前面说过MediaBrowserServiceCompat的媒体播放其实是通过关联的MediaSessionCompat来实现的,而其关联方式也很简单:

MediaSessionCompat mSession = new MediaSessionCompat(this, "MusicService");
setSessionToken(mSession.getSessionToken());
mSession.setCallback(new MediaSessionCompat.Callback());
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);//MediaSessionCompat的播放控制则又全部是通过接口MediaSessionCompat.Callback来实现的
@Overridepublic void onPlay() {
//点击播放按钮时触发
//通过MediaControllerCompat .getTransportControls().play();触发}@Overridepublic void onSkipToQueueItem(long queueId) {//播放指定对列媒体时触发//通过MediaControllerCompat .getTransportControls().onSkipToQueueItem(queueId);触发}@Overridepublic void onSeekTo(long position) {//设置到指定进度时触发//MediaControllerCompat.getTransportControls().seekTo(position);}@Overridepublic void onPlayFromMediaId(String mediaId, Bundle extras) {
//播放指定媒体数据时触发
//MediaControllerCompat.getTransportControls().playFromMediaId(mediaItem.getMediaId(), null);        }@Overridepublic void onPause() {
//暂停时触发
//MediaControllerCompat.getTransportControls().pause();}@Overridepublic void onStop() {
//停止播放时触发
//MediaControllerCompat.getTransportControls().stop();}@Overridepublic void onSkipToNext() {
//跳到下一首时触发
//MediaControllerCompat.getTransportControls().skipToNext();}@Overridepublic void onSkipToPrevious() {
//跳到上一首时触发
//MediaControllerCompat.getTransportControls().skipToPrevious();}
//当然还有很多回调函数,大家可以自行查看
}

MediaControllerCompat

媒体控制器在上面已经介绍了其创建和关联方式,而它控制播放器状态的方式在上面的代码注释中已经说明了,基本上都是通过MediaControllerCompat.getTransportControls()来进行控制的。

到这里媒体服务的相关使用和注意点已经介绍完了,使用这套api来实现音乐APP还是很方便很快捷的,而且我们可以很方便的切换播放器,如MediaPlayer,ExoPlayer等,如有建议和问题欢迎在博客关于页中扫码加QQ群交流。

关于媒体浏览器服务(MediaBrowserService)相关推荐

  1. 360安全服务器组件怎样禁止,如何禁用360安全浏览器服务组件?如何正确的操作...

    使用过360浏览器的用户都知道360浏览器是一个喜欢捆绑组件的服务软件,用户可以使用在平台上获取更多的资源,其实只要简单的几步就可以马上阻绝这些垃圾组件的运行,用户如果想要使用,那么就和小编一起来使用 ...

  2. DAO,除了协议、社交、媒体、服务之外还能发展哪个领域?

    DAO,除了协议.社交.媒体.服务之外还能发展哪个领域? 互联网为通信做了什么,DAO也可以为资本做什么. 互联网和社交网络使得志同道合的人比以往任何时候都更容易交流,而且不受地理位置的限制.数字原生 ...

  3. TBS腾讯浏览器服务x5内核打开本地doc(doc docx xlsx pdf ppt)文档(官网最新43903版本SDK)

    目前最新版本(官网最新43903版本SDK)仅支持本地文件查看 测试Demo:TBS腾讯浏览器服务x5内核打开本地doc(docdocxxlsxpdfppt)文档(官网最新43903版本SDK)-互联 ...

  4. 360浏览器服务组件怎么关闭,开机总是弹出新闻窗

    方案一: 到目录F:\ProgramFiles(x86)\360se6\Application\components\sesvc下查看文件sesvc.exe的属性也可以看到该文件的描述为360安全浏览 ...

  5. java 直播媒体流服务(ffmpeg、javacv)支持本地视频、网路视频

    还在为视频推流和拉流而烦恼吗?还在为安装nginx.ffmpeg而头疼吗?只需要两步就可以省去这些烦恼,第一步:推流 第二步:播放,你确定不入手么 一.添加媒体流服务依赖包 maven pom.xml ...

  6. 京东智联云媒体处理服务再升级

    视频截图是提供视频直播或点播服务的企业,在打造产品过程中经常会应用到的一项服务,可以极大提高视频节目的重复利用,生成动图.视频封面,或用于抽帧鉴黄,满足监管需求.本文将介绍用于直播/点播中的视频截图服 ...

  7. 智能媒体管理服务控制台功能体验

    Step1: 浏览器中输入网址 console.aliyun.com Step2: 输入阿里云账号和阿里云账号密码 Step2-2: 选择不绑定手机 Step3: 进入智能媒体管理(在 存储与CDN ...

  8. windows下基于wvp-GB28181-pro+ZLMediaKit实现的GB28181媒体流服务+实现ssl证书配置实现https访问

    需要实现摄像头接入功能,实现录像回放功能,并且预算有限,没有硬盘录像机,没有vpn路由器,只有能联网的摄像头,经过一周的努力,终于实现了全部的功能. 首先准备工作,需要准备的软件有 1.git,必不可 ...

  9. Android 媒体播放框架MediaSession分析与实践

    版权声明:本文为博主原创文章,未经博主允许不得转载 源码:AnliaLee/BauzMusic 大家要是看到有错误的地方或者有啥好的建议,欢迎留言评论 前言 最近一直在忙着学习和研究音乐播放器,发现介 ...

最新文章

  1. 一年春事,桃花红了谁……
  2. 树莓派4B装载ROS系统启动摄像头
  3. 如何活着:欲望、外界、标签、天才、时间、人生目标和经历
  4. Android Studio 生成签名的APK
  5. enum in c language
  6. (35)FPGA原语设计(BUFGCTRL)
  7. Hibernate配置文件与关联映射介绍
  8. 深信服AC本地用户密码认证配置
  9. 信号与系统——初识信号的原理与分类
  10. matlab画图的参数,matlab画图参数
  11. 黑苹果教程 欸嘿嘿~
  12. diy服务器个人主机_电脑小白如何自己动手DIY主机?
  13. IE浏览器js 中http请求,中文传参报400错误-解决方法
  14. 聚币网API[Python3版]
  15. fnv1 java_笔记本热键驱动_笔记本万能fn键驱动 v1.1 通用版-126g驱动网
  16. 量化金融基本模型及方法讲习班系列笔记——‘AI与金融工程’
  17. python中pass与break区别
  18. 计算机打印机密码怎么设置,如何设置电脑开机密码(电脑如何安装打印机)
  19. ARMV7-M架构---Part A :Application Level Architecture---A1 Introduction
  20. 生成Aprilgrid标定板

热门文章

  1. 电力电子领域的几款软件的对比分析
  2. MySql_RDBMS简介
  3. 使用Python进行图像处理
  4. ambe1000 音频芯片解码压缩分析
  5. 创业投资10万以内的小生意推荐,你GET到了吗?
  6. Smart Package Robot,高级安装记录器和 RPA 脚本系统
  7. Filecoin之环境安装
  8. 谁说女生不可以学编程?维密超模放弃年薪千万,一心只当程序媛
  9. 当你孤独,抑郁,焦虑的时候......请记得,还有风雨
  10. python画大耳朵图图_简笔画教程:怎么画大耳朵图图