基于Android的MediaPlayer的音乐播放器的封装

使用过android原生的mediaplayer来做音频播放的同学们,肯定是经历过一些痛苦的,因为android提供了一个状态机,确实这个状态机是需要的,不过这个状态不对,就要往外抛出异常,并且如果在程序中,不能得知mediaplayr的状态,这个是着实让人头疼,个人之前写过mediaplayer的一个封装,将这些状态的获取以及操作进行了简化

封装的链接地址: PandaPan音频处理

1 原生的mediaplayer

android原生的mediaplayer,简单做一下介绍,mediaplayer顾名思义,就是用于多媒体播放的,这个类,是可以做音频和视频流的播放的是基于android的多媒体框架做的,android的多媒体框架,支持的音频格式也是有限的, 支持的格式的链接如下: android多媒体支持的格式, 能够看到,其实还是挺头疼的, 要想在android的主流版本上支持一些高清的格式,例如flac,ape等,你看,mediaplayer还是不靠谱的,那就得自己做这块的音频的解析啦, 可以有几种方式,

方式1: native解码, java层操作

一种就是使用原生的解码器,解出来为pcm数据,然后使用android的audio来播放,不过这种方式,还需要将数据通过native层解析,然后交给java层来处理,这种方式呢,比较适合我们找到对应的codec,来处理,而这些codec,官方是提供的,但是针对不同的格式,也是需要自己写不同的java层,来封装好各种格式的数据,最终给audioTrack来使用,挺费劲的

方式2: native解码与播放

就是将解码与播放,都使用native来播放,android的native播放音频模块是OpenSL ES,这种方式比较好,原因如下:

  1. native效率高,不需要和java层多次交互
  2. 我们java工程师,需要做的事情就比较少啦,哈哈

说了这些擦边的,回归到正题

为什么要做再次的封装,原因汇总如下:

  1. android 原生的mediaplayer,容易抛出异常,而且没有状态的获取,很容易出现问题
  2. android的音频状态机设计的也是比较复杂的,你看看官网中提供的这个状态机的图 当然也是因为android的官方,做的很细致,但是这给我们只是想播放音频带来了一些麻烦
  3. 可替换性不强,因为直接使用mediaplayer的相关接口,假如我们要播放一些我们不支持的音频的格式的话,那么估计就要写很多的if else了,这样肯定不是我们想要的,我们想用的是接口简单方便使用,而且可以替换的,那么这就涉及面向接口的编程啦

2 mediaplayer的再次设计

上面说的原因那么多,这其实就是我们再次设计的需求:转换为对应的需求:

  1. 提供接口,支持播放,暂停,继续播放,停止播放,seekTo()
  2. 获取当前播放器的状态,获取播放的路径, 时长, 是否正在播放
  3. 提供接口,可以对其设置监听,可以得知当前播放器状态的变化

2.1 状态的再次设计

基于这么几点,以及android原生播放器的状态图,以及在不同状态支持的操作,我将android的mediaplayer的状态进行了简化.

总共有五个状态

  • 空闲状态 IDLE (对应mediaplayer中的Idle)
  • 初始化状态 INITIALIZED(对应MediaPlayer的Initialized)
  • 准备中的状态 PREPARING (对应MediaPlayer的Preparing)
  • 准备好的状态 PREPARED (对应mediaplayer的Prepared)
  • 运行中的状态 RUNNING (对应mediaplayer的Started +Paused)

大家可能会有疑问,那么其他的状态,其实其他的状态被我直接给简化处理了

图中的End,ErrorPlayerbackComplete状态都直接将mediaplayer给清空了,将Mediaplayer直接重新设置为新的mediaplayer,恢复到了IDLE状态,因而简化了N多操作

2.2 向外通知变化

上面我们提供的状态变化,会向外做通知

Preparing –> Prepared –> (Pause + Play) – {OnErro/OnStopped/OnComplete}

OnProgressChanged

2.3 疑问解答

大家可能会提到,为什么不把循环播放,以及自动播放下一首放到这个类实现?愿意如下:

  1. 类要分功能和模块,这个类,只是用作状态的封装,不应该添加其他功能
  2. 在正常的工程中,我们要实现的循环播放,对应的数据,应该不只是简单的一个路径,对应的肯定是一些MediaInfo的数据,可能有title,artist等数据,这个我可以后续再次添加一个类,做这样的功能,内部调用StatedMediaPlayer即可

工程代码

封装的链接地址: PandaPan音频处理 这个工程下的类地址:

https://github.com/yqpan1991/DroidAudio/blob/master/app/src/main/java/droidaudio/apollo/edus/com/droidaudio/multimedia/media/StatedMediaPlay.java

更多相关文章

  1. Android(安卓)播放Gif 动画
  2. Android中shape的使用
  3. Android(安卓)广播监听网络状态
  4. Android内存管理机制之一:lowmemory killer
  5. 填坑总结:通过selector的android:state_checkable和android:state
  6. android中流媒体
  7. Android(安卓)播放Gif 动画
  8. 浅谈android的selector,背景选择器(看着有用就转载了)
  9. Android我还可以相信你多少系列文章二之音视频播放

随机推荐

  1. 详细介绍把数据转换成XML格式的好处
  2. 使用JavaScript访问XML数据
  3. 使用XML实现BBS(主题列表篇)的详情介绍
  4. XML在语音合成中的应用
  5. HTML中的XML数据岛记录编辑与添加的详细
  6. 如何得到XML文档大小的详细介绍
  7. 用XML和XSL来生成动态页面
  8. 利用XMLBean轻轻松松读写XML
  9. XML文档搜索使用小结
  10. XML的简单读取与写入的详解