很多同学,在学习安卓的时候,可能会完成一个音乐播放器的项目,因为音乐播放器项目会贯穿安卓的四大组件。在项目中,大家一定会在服务中使用MediaPlayer去播放音乐,但是界面如何控制服务进行音乐的更换、改变播放进度,大家往往会使用发送广播的方式去通知服务,同时,服务可以发送广播通知界面播放进度的变化。

这时候问题来了:

  1. 你喜欢在广播接受者中完成解析数据变为指令的代码吗?
  2. 你觉得用广播高效吗?

当然,你可以通过binder做为服务的代理来进行通讯,但是对于服务和界面的同步则又略显捉急。(如果做过音乐播放器的同学当然知道我在说些什么)

在安卓5中,谷歌推出了MediaSession框架专门解决媒体播放时界面和服务通讯问题。

要理解MediaSession框架,分别看看Media和Session:首先Media是媒体的意思,也就是说这个框架用于音视频媒体;而Session呢,翻译成中文就是会话的意思。一个会话,肯定是涉及两方或以上;在MediaSession框架中,有受控端(一个)和控制端(可以有多个)。接下来为了保证受控端和控制端不串号(想象一个遥控器可以遥控同一型号的多台电视),就有了SessionToken的概念,相当于我们在连接蓝牙设备时的配对码,这样就保证了不串号。在MediaSession框架中,最重要的三个类的概念就这么多,接下来我们一起看看如何使用MediSession框架。

先放一张框架示意图:

上图你看了可能会丈二和尚摸不清头脑,请耐心地看下面的内容,一会回来看,你会觉得更加清晰了。框架的主要类:

一、基本框架搭建

  1. 在服务中通过new MediaSession( Context, String)构造出MediaSession,其中字符串可以传入包名(或任意)
  2. 在服务中调用mediaSession.getSessionToken获得Token对象
  3. 通过IBinder把Token传递给绑定服务的Activity
  4. 在Activity中绑定服务,拿到Token对象,并调用MediaController(Context, MediaSession.Token)获得MediaController对象

二、设备上的音乐加载

以上就完成了MediaSession框架的搭建。接下来就开始使用这个框架了。接下来我们看看如何使用框架去完成音乐列表加载。
1、 服务中通过MediaStore内容提供者查询设备上的音乐得到Cursor对象
2、 遍历Cursor把查询的结果封装到List集合中MediaMetadata可以看作是一个map集合,键是String(需要MediaMetadata上的常量),值是音乐名称、歌手、时常等信息
3、 把List转化成ListQueueItem和MediaMetadata是什么关系呢?QueueItem在构造的时候,需要MediaDescription,而MediaDescription可以通过MediaMetadata获得。在构造QueueItem时,注意id不重复。
4、 服务中的MediaSession调用setQueue(List)方法,来告知整个框架的各方,目前有哪些音乐可以播放。
5、 界面上可以通过MediaController的getQueue方法获得播放列表(List)。当然了因为服务对音乐列表的查询封装会需要一些时间,那也可以给调用mediaController.registerCallback(MediaController.Callback) 给mediaController注册一个监听,每当受控端调用了setQueue方法,所有的回调的onQueueChanged(List)都会被调用

三、音乐的播放

1、在Activity中调用MediaController的getTransportControls()获得TransportControls对象

2、在播放按钮的点击事件上,调用TransportControls的play方法,

3、为了接受到界面上的play指令,需要在服务端的MediaSession上调用setCallback(MediaSession.Callback)方法,并实现MediaSession.Callback的onPlay方法

4、在onPlay方法中,服务端可以从播放列表中选取一首音乐去播放,

5、这时候界面上并不知道音乐已经播放了,就需要服务去通知界面,开始播放音乐了,服务中需要调用MediaSession的setPlaybackState(PlaybackState) 去通知界面开始播放了,对于PlaybackState对象,需要用它的构造去Builder去构造,你可以简单的只用setState(int state, long position, float playbackSpeed)方法,其中state是PlaybackState的常量、position就是当前播放位置(可以从MediaPlayer上去获取),而playbackSpeed默认是1就好了

6、现在界面要想知道播放状态发生变化了,可实现MediaController.Callback的onPlaybackStateChanged方法,判断如果状态是正在播放,则可以改变播放按钮的状态为暂停样式。现在你可以再看一遍上面的步骤,然后对照示意图。需要特别说明的是MediaSession框架只负责通讯,并不涉及任何业务逻辑,具体对MediaPlayer的方法调用、音乐加载、最重要的就是明白TransportControls方法和MediaSession.Callback回调的对应关系

以及MediaSession的方法和MediaController.Callback的回调方法

四、MediaSession的精妙之处

MediaSession框架中个人感觉最妙的部分就是播放进度的获取了

如果在原来,可通过不断地调用MediaPlayer的getPosition获取播放进度,但如果项目的整体架构比较好的话,界面是拿不到MediaPlayer对象的。在MediaSession框架中,完全不需要去获取播放进度,当然前提是播放状态是准确的。

我们来看看PlaybackState.Builder的setState方法:

setState(int state, long position, float playbackSpeed)
setState(int state, long position, float playbackSpeed, long updateTime)

第二个的方法比第一个的多了一个参数叫更新时间,其实第一个方法会调用第二个方法,并指定更新时间为开机至今的时间(因为开机时间无法更改,系统时间可以改)。
在界面上上如何获得当前播放进度呢:
计算公式如下

((获取当前开机时间 – 上次更新状态的时间)* 播放速度 +上次更新状态时的播放进度)

代码如下

long currentPosition = ((SystemClock.elapsedRealtime() – playbackState.getLastPositionUpdateTime() ) * playbackState. getPlaybackSpeed() ) + playbackState.getPosition();

总结:

MediaSession框架对于播放的各种需求都非常优雅地提供了实现,这些都等待你的发现,而且还提供了扩展的控件,可以自己完成一些自定义的请求。

具体的代码,可以参照谷歌官方的项目:https://github.com/googlesamples/android-UniversalMusicPlayer。正常运行项目需要翻墙,因为这个应用的音乐资源是从youtube上加载的。在看代码的时候需要把无关代码快速跳过,把握主线。

现在有同学可能会问了,MediaSession框架只能在安卓5系统上使用,但现在安卓5的市场占有率还比较低,如何兼容低版本呢?Google公司在support-v4(21以上版本)中也提供了MediaSessionCompact(android.support.v4.media.session.MediaSessionCompat)兼容包。具体API大同小异。

原文链接:http://bbs.itcast.cn/thread-86046-1-1.html

MediaSession框架介绍相关推荐

  1. python爬虫scrapy框架教程_Python爬虫教程-30-Scrapy 爬虫框架介绍

    从本篇开始学习 Scrapy 爬虫框架 Python爬虫教程-30-Scrapy 爬虫框架介绍 框架:框架就是对于相同的相似的部分,代码做到不出错,而我们就可以将注意力放到我们自己的部分了 常见爬虫框 ...

  2. 2019年上半年收集到的人工智能开源框架介绍文章

    2019年上半年收集到的人工智能开源框架介绍文章 TensorFlow基本使用 TensorFlow.js:让你在浏览器中也能玩转机器学习 人工智能学习框架TensorFlow渐近分析 TensorF ...

  3. ESFramework网络通信框架介绍之(2)――网络通信消息NetMessage

    ESFramework网络通信框架与元数据 较之C++而言,.NET是一个更加"动态"的平台,其动态能力建立在反射机制之上,而反射的基础是"元数据". 上文已经 ...

  4. dommel mysql_.Net Core AA.FrameWork应用框架介绍

    开发多年,一直在从社区获取开源的便利,也深感社区力量的重要性,今天开源一个应用基础框架AA.FrameWork,也算是回馈社区,做出一点点贡献,希望能够帮助类似当年入行的我. AA.FrameWork ...

  5. Foundation框架介绍

    Foundation框架介绍 前言 在开发初期,个人发现开发主要涉及到这几个方面:语言语法使用.UIKit.Foundation, 语言是开发基础,UIkit主要负责用户界面设计,其他最常用的就是Fo ...

  6. 【Django】创建项目及框架介绍,学习笔记(一)

    [学习教程] 1.Django基础教程:https://code.ziqiangxuetang.com/django/django-tutorial.html 2.Django博客:http://ww ...

  7. 流行的9个Java框架介绍: 优点、缺点等等

    流行的9个Java框架介绍: 优点.缺点等等 在 2018年,Java仍然是世界上最流行的编程语言.它拥有一个巨大的生态系统,在全世界有超过900万Java开发人员.虽然Java不是最直接的语言,但是 ...

  8. iOS流媒体直播整个框架介绍(HLS、RTSP)

    iOS流媒体直播整个框架介绍(HLS.RTSP) 目录技术文章2016年7月17日 一.HTTP(WebService) 基于HTTP的渐进下载Progressive Download流媒体播放仅是在 ...

  9. fitnesse - 框架介绍

    fitnesse - 框架介绍 2017-09-29 目录: 1 fitnesse是什么? 2 框架介绍 3 与junit.testng比较,fitnesse教其他框架有什么优势 1 fitnesse ...

最新文章

  1. Objective-C学习笔记(十九)——对象方法和类方法的相互调用
  2. python globals().get,python – 为什么人们会使用globals()来定义变量
  3. Java集合中的排序API分析
  4. Docker将镜像上传至私有仓库
  5. Bridge(桥接)--对象结构模式
  6. python超市买苹果_官网购买的iPhone12pro还没发货?试着用Python快速入手
  7. 拆解嘀嗒出行赴港IPO招股书:顺风车市占率近七成 2019年起实现盈利
  8. http请求转为https请求 java_如何将Javaweb工程的访问协议由http改为https及通过域名访问?...
  9. java解码acc音频文件_(JAVA)将(acc/m4a)音频转换成Mp3格式
  10. 编程英文单词的标准缩写
  11. 创建FB-定义接口(基础版)
  12. 偏最小二乘法PLS和PLS回归的介绍及其实现方法
  13. elixer学习笔记
  14. 32位int 最小负整数
  15. Python实现经纬度转换
  16. [转]SMART原则
  17. 杰出校友王章清董事长
  18. 项目实训2021.06.28
  19. B.数据挖掘机器学习[五]---汽车交易价格预测详细版本{模型融合(Stacking、Blending、Bagging和Boosting)}
  20. 轻量级网络:Bottleneck结构(沙漏型结构)

热门文章

  1. mysql Decimal(M,D)解释
  2. 【转载】MongoDB安装并随windows开机自启
  3. RTEMS 4.9.4 bootcard.c 中的 boot_card 函数分析
  4. c# 扩展方法奇思妙用变态篇四:string 的翻身革命
  5. WinRAR4.11-64Bit最简易的注册方法
  6. Scala 基础(4)—— 类和对象
  7. 【C++】源自指针的报错
  8. C#中的快捷键,可以更方便的编写代码
  9. 解决mysql插入数据时出现Incorrect string value: '\xF0\x9F...' 的异常
  10. struts入门day04