Android -- MediaPlayer基础简介

MediaPlayer是Android中的一个多媒体播放类,我们能通过它控制音视频流或本地音视频资源的播放过程。

这段时间查阅了Android官方文档对MediaPlayer的介绍,同时也看了一些书籍介绍。现在把MediaPlayer的基础内容在此做一个记录,以供后面查阅、回忆。

MediaPlayer系统的主要代码实现介绍如下:

1、Java部分

MediaPlayer.java

Java类主要的路径在\frameworks\base\media\java\android\media\MediaPlayer.java
2、Native部分
MediaPlayer.java中的功能实现都借助JNI调到Native层,JNI主要实现在\frameworks\base\media\jni\android_media_MediaPlayer.cpp,这部分编译会得到libmedia_jni.so库。
多媒体底层库的代码实现主要在\frameworks\av\media\libmedia\目录下,这部分编译得到的是libmedia.so库。
最后多媒体服务部分的代码实现主要在\frameworks\av\media\libmediaplayerservice\目录下,这部分编译得到的是libmediaplayerservice.so库。
这三个库的调用关系如图所示:MediaPlayer.java -> libmedia_jni.so -> libmedia.so -> libmediaplayerservice.so.
下图是一个MediaPlayer对象被支持的播放控制操作驱动的声明周期和状态。其中,椭圆代表MediaPlayer可能驻留的状态,弧线表示驱动MediaPlayer在各个状态之间迁移的播放控制操作。这里有两种类型的弧线。由单箭头开始的弧线代表同步方法调用,而以双箭头开头的弧线代表异步方法调用。图片介绍来源于官方文。
通过上图,我们知道一个MediaPlayer对象有如下几种状态。
  1. 当一个MediaPlayer对象被刚刚用new操作符或者是调用了reset()方法后,就处于Idle状态。当调用了release()方法后,处于End状态。这两种状态之间是MediaPlayer对象的生命周期。
     在一个新构建的MediaPlayer对象和一个调用了reset()方法的MediaPlayer对象之间有一个微小但十分重要的差别。当处于Idle状态时,调用 getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int), prepare() or prepareAsync()方法都是错误的。当一个MediaPlayer对象刚被创建时,内部的播放引擎和对象的状态都没有改变,这时调用以上方法,框架无法回应客户端程序注册的OnErrorListener.onError()方法;但若这个对象调用了reset()方法后,再调用以上方法,内部的播放引擎就会回调客户端程序注册的OnErrorListener.onError()方法,并将错误的状态传入。
当一个MediaPlayer对象不再被使用时,应立即调用release()方法来释放在内部的播放引擎与这个MediaPlayer对象关联的资源。资源可能包括硬件加速组件的单态固件,若没有调用release()方法可能会导致之后的MediaPlayer对象实例无法使用这种单态硬件资源,从而导致程序异常。一旦MediaPlayer对象进入了End状态,将不能再被使用,也没有办法再迁移到其他状态。
此外,使用new操作符创建的MediaPlayer对象处于Idle状态,而那些通过重载的create()方法创建的MediaPlayer对象却不是处于Idle状态。事实上,如果成功调用了重载的create()方法,这些对象就已经是Prepare状态了。
   
    2. 一般情况下,由于种种原因一些播放控制操作可能会失败,如不支持的音频/视频格式、缺少隔行扫描的音频/视频、分辨率太高、流超时等,因此,错误报告和恢复在这种情况下是非常重要的。有时由于编程错误,在处于无效状态的情况下调用了一个播放器控制操作的情况是可能发生的。在所有这些错误条件下,内部播放引擎会调用一个由客户端程序提供的OnErrorListener.onError()方法。客户端程序可以通过调用 setOnErrorListener(android.media.MediaPlayer.OnErrorListener)方法注册OnErrorListener对象。
一旦发生错误,MediaPlayer对象会进入Error状态。为了重用一个处于Error状态的MediaPlayer对象,可以调用reset()方法把这个对象恢复到Idle状态。注册一个OnErrorListener来获知内部播放引擎发生的错误是一个好的编程习惯。在不合法的状态下调用一些方法,如prepare()、prepareAsync()和setDataSource()等会抛出ILlegalStateException异常。
    3. 调用 setDataSource(FileDescriptor), setDataSource(String), setDataSource(Context, Uri), setDataSource(FileDescriptor, long, long)方法会使处于Idle状态的对象迁移到Initialized状态。若当此MediaPlayer对象处于其他状态下,调用setDataSource()方法会抛出 ILlegalStateException异常。时刻注意调用setDataSource()方法可能会抛出的ILlegalStateException异常和IOException异常是一个好的编程习惯。
    4. 在开始播放前,MediaPlayer对象必须要进入Prepared状态。有两种方法可以使MediaPlayer对象进入Prepared状态。
        (1)、调用prepare()方法(同步):此方法返回就表示该MediaPlayer对象已经进入了Prepared状态。
        (2)、调用prepareAsync方法(异步):此方法会使MediaPlayer对象进入Preparing状态并返回,内部的播放引擎会继续未完成的工作。
当同步版本返回或异步版本的准备工作完全完成时就会调用客户端程序提供的OnPrepareListener.onPrepared()监听方法。可以调用方法MediaPlayer.setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)来注册OnPreparedListener。
Preparing是一个中间状态,如果在此状态下调用任何影响播放功能的方法,最终的运行结果都是未知的。在不合适的状态下调用prepare()和prepareAsync()方法会抛出ILlegalStateException异常。当MediaPlayer对象处于Prepared状态时,可以调整音视频的属性,如音量、播放时是否一致亮屏、循环播放等。
    5. 在要开始播放时必须调用start()方法。当此方法成功返回时,MediaPlayer对象处于Started状态。isPlaying()方法可以被用来测试某个MediaPlayer对象是否处于Started状态。
当处于Started状态时,内部播放引擎会调用客户端程序提供的OnBufferingUpdateListener.onBufferingUpdate()回调方法,此回调方法允许应用程序追踪流播放的缓冲状态。对一个已经处于Started状态的MediaPlayer对象调用start()方法没有影响。
    6. 播放可以被暂停、停止,以及调整播放进度。当调用pause()方法并返回时,会使MediaPlayer对象进入Paused状态。注意Started与Paused状态的相互转换在内部的播放引擎中是异步的,所以可能需要一点时间在isPlaying()方法中更新状态,若在播放流内容,这段时间可能会有几秒钟。
调用start()方法会让一个处于Paused状态的MediaPlayer对象从之前的暂停状态恢复到播放状态。当start()方法返回时,MediaPlayer对象的状态又会变成Started状态。对一个已经处于Paused状态的MediaPlayer对象,调用pause()方法没有任何影响。
    7. 调用stop()方法会停止播放,并且还会让一个处于Started、Paused、Prepared或者PlaybackCompleted状态的MediaPlayer对象进入Stopped状态。对一个已经处于Stopped状态的MediaPlayer对象,调用stop()方法没有影响
    8. 调用seekTo()方法可以调整播放的位置。方法seekTo(int)是异步执行的,所以可以马上返回,但是实际的定位播放操作可能需要一段时间才能完成,尤其是播放流形式的音视频。当实际的定位播放操作完成后,内部的播放引擎会调用客户端程序提供的OnSeekComplete.onSeekComplete()回调方法。可以通过setOnSeekCompleteListener(OnSeekCompleteListener)方法注册。
在此需要注意,seekTo(int)方法也可以在其他状态下调用,例如Prepared、Paused和PlaybackCompleted状态。此外,目前的播放位置,实际可以调用getCurrentPosition()方法得到,可以帮助如音乐播放器之类的应用程序不断更新播放进度。
    9. 当播放到流的末尾时,这次播放操作就彻底完成。如果调用setLooping(boolean)方法开启了循环模式,那么这个MediaPlayer对象就会重新进入到Started状态。如果没有开启循环模式,那么内部的播放引擎会调用客户端程序提供的OnCompletion.onCompletion()回调方法。可以通过调用MediaPlayer.setOnCompletionListener(OnCompletionListener)方法来设置。内部的播放引擎一旦调用了OnCompletion.onCompletion()方法,说明这个MediaPlayer对象进入了PlaybackCompleted状态。当处于PlaybackCompleted状态时,可以调用start()方法来让这个MediaPlayer对象再次进入Started状态。
MediaPlayer方法的有效状态和无效状态
方法 有效状态 无效状态 Comments
attachAuxEffect {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Error} This method must be called after setDataSource. Calling it does not change the object state.
getAudioSessionId any {} This method can be called in any state and calling it does not change the object state.
getCurrentPosition {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getDuration {Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getVideoHeight {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getVideoWidth {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
isPlaying {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
pause {Started, Paused, PlaybackCompleted} {Idle, Initialized, Prepared, Stopped, Error} Successful invoke of this method in a valid state transfers the object to the Paused state. Calling this method in an invalid state transfers the object to the Error state.
prepare {Initialized, Stopped} {Idle, Prepared, Started, Paused, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Preparedstate. Calling this method in an invalid state throws an IllegalStateException.
prepareAsync {Initialized, Stopped} {Idle, Prepared, Started, Paused, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Preparingstate. Calling this method in an invalid state throws an IllegalStateException.
release any {} After release(), the object is no longer available.
reset {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} {} After reset(), the object is like being just created.
seekTo {Prepared, Started, Paused, PlaybackCompleted} {Idle, Initialized, Stopped, Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
setAudioAttributes {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method does not change the state. In order for the target audio attributes type to become effective, this method must be called before prepare() or prepareAsync().
setAudioSessionId {Idle} {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} This method must be called in idle state as the audio session ID must be known before calling setDataSource. Calling it does not change the object state.
setAudioStreamType {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method does not change the state. In order for the target audio stream type to become effective, this method must be called before prepare() or prepareAsync().
setAuxEffectSendLevel any {} Calling this method does not change the object state.
setDataSource {Idle} {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Initializedstate. Calling this method in an invalid state throws an IllegalStateException.
setDisplay any {} This method can be called in any state and calling it does not change the object state.
setSurface any {} This method can be called in any state and calling it does not change the object state.
setVideoScalingMode {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Error} Successful invoke of this method does not change the state.
setLooping {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
isLooping any {} This method can be called in any state and calling it does not change the object state.
setOnBufferingUpdateListener any {} This method can be called in any state and calling it does not change the object state.
setOnCompletionListener any {} This method can be called in any state and calling it does not change the object state.
setOnErrorListener any {} This method can be called in any state and calling it does not change the object state.
setOnPreparedListener any {} This method can be called in any state and calling it does not change the object state.
setOnSeekCompleteListener any {} This method can be called in any state and calling it does not change the object state.
setScreenOnWhilePlaying any {} This method can be called in any state and calling it does not change the object state.
setVolume {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method does not change the state.
setWakeMode any {} This method can be called in any state and calling it does not change the object state.
start {Prepared, Started, Paused, PlaybackCompleted} {Idle, Initialized, Stopped, Error} Successful invoke of this method in a valid state transfers the object to the Started state. Calling this method in an invalid state transfers the object to the Error state.
stop {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method in a valid state transfers the object to the Stopped state. Calling this method in an invalid state transfers the object to the Error state.
getTrackInfo {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
addTimedTextSource {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
selectTrack {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
deselectTrack {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.

MediaPlayer中可使用的回调

在播放过程中,应用程序也许会想去注册一些回调函数来获取一些内部状态更新或运行错误的事件信息。所有这些都可以通过正确的设置一些监听对象来实现:

setOnPreparedListener(OnPreparedListener)setOnPreparedListener,

setOnVideoSizeChangedListener(OnVideoSizeChangedListener)setOnVideoSizeChangedListener,

setOnSeekCompleteListener(OnSeekCompleteListener)setOnSeekCompleteListener,

setOnCompletionListener(OnCompletionListener)setOnCompletionListener,

setOnBufferingUpdateListener(OnBufferingUpdateListener)setOnBufferingUpdateListener,

setOnInfoListener(OnInfoListener)setOnInfoListener,

setOnErrorListener(OnErrorListener)setOnErrorListener, etc

为了能通过这些监听器正确收到相关联的回调,在创建MediaPlayer对象时,要确保它所在的线程必须有自己的消息循环(Looper)。

MediaPlayer中的内嵌类
interface MediaPlayer.OnBufferingUpdateListener Interface definition of a callback to be invoked indicating buffering status of a media resource being streamed over the network. 
interface MediaPlayer.OnCompletionListener Interface definition for a callback to be invoked when playback of a media source has completed. 
interface MediaPlayer.OnErrorListener Interface definition of a callback to be invoked when there has been an error during an asynchronous operation (other errors will throw exceptions at method call time).  
interface MediaPlayer.OnInfoListener Interface definition of a callback to be invoked to communicate some info and/or warning about the media or its playback. 
interface MediaPlayer.OnPreparedListener Interface definition for a callback to be invoked when the media source is ready for playback. 
interface MediaPlayer.OnSeekCompleteListener Interface definition of a callback to be invoked indicating the completion of a seek operation. 
interface MediaPlayer.OnTimedTextListener Interface definition of a callback to be invoked when a timed text is available for display. 
interface MediaPlayer.OnVideoSizeChangedListener Interface definition of a callback to be invoked when the video size is first known or updated  
class MediaPlayer.TrackInfo Class for MediaPlayer to return each audio/video/subtitle track's metadata.

PS:以上所有内容都可以到MediaPlayer Android官方文档获取更准确的介绍。

Android -- 多媒体播放之MediaPlayer基础简介相关推荐

  1. Android 自动化测试 Espresso篇:简介基础使用

    前言 最近在尝试深入学习Android单元测试. 以前笔者对于单元测试的理解很简单,做一个简单的API测试获取Server端数据,或者测试对应简单的工具类和数据处理的逻辑. 经过这近一个月的碎片化学习 ...

  2. 快速接入 Android BLE 开发的基础框架

    代码地址如下: http://www.demodashi.com/demo/12092.html * Android BLE基础操作框架,基于回调,操作简单.包含扫描.多连接.广播包解析.服务读写及通 ...

  3. 第一章 android以及智能手机行业相关简介

    第一章 android以及智能手机行业相关简介读后感受&知识累计 最近深刻了解到自己基础知识的不足,变不断的开始阅读很多android相关的知识,希望这些对本人未来的职业发展有很大的帮助.下面 ...

  4. Android 编译之make基础(转)

    Android 编译之make基础 原文链接 qiuxintai 0.498 2020.10.14 18:52:40 字数 13,246 阅读 2,631 引言 做android系统相关的开发已经有几 ...

  5. Android音视频开发基础(七):视频采集-系统API基础

    前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了<Android 音视频从入门到提高 - 任务列表>.本文是Android音视 ...

  6. Android DRM框架与基础知识

    Android DRM框架与基础知识 Android DRM框架 DRM框架的目的:能让安卓设备可以播放更多的内容,不同的内容和硬件设备可能使用的是不同的内容版权保护机制或者没有版权管理机制,但是安卓 ...

  7. android java框架_Android 框架简介:java框架

    Android 框架简介:java框架 2015-10-15 14:43  来源: 正保IT教育网整理 这里简单的介绍了Android的java环境基础,在后面一节中会结合具体的实例来理解这一节的内容 ...

  8. Android ble连接过程,Android BLE的一些基础知识及相关操作流程 - 全文

    前言: 本文主要描述Android BLE的一些基础知识及相关操作流程,不牵扯具体的业务实现,其中提供了针对广播包及响应包的解析思路,希望对正在或即将面临Android BLE开发的伙伴们有所引导. ...

  9. Android多媒体播放器源码解析(stagefright框架)

    一.android多媒体播放的调用步骤: a) android中定义一个MediaPlayer类 b) 在MediaPlayer中使用JNI技术调用的是android_media_MediaPlaye ...

最新文章

  1. 使用Intellij Idea 创建一个Web项目!
  2. Vue父子组件通信小总结
  3. ipad写python_ipad怎么写python
  4. Javascript 面向对象编程初探(一)--- 封装
  5. linux简单快速启用web
  6. php function split is deprecated,如何解决php Function split() is deprecated 的问题
  7. spring boot (3.自动配置@enableautoconfiguration)
  8. 当C++爬山壁纸——C++山寨版
  9. 中国软件开发project师之痛
  10. 2021-2025年中国制药行业MR报告软件行业市场供需与战略研究报告
  11. 计算机与管理科学的交叉与融合,计算机信息管理学科交叉融合研究论文
  12. Javamysql语法转化oracle_MyBatis项目实战 快速将MySQL转换成Oracle语句
  13. 118. PHP 性能问题
  14. linux 配置 NTP 服务器
  15. 百科知识:呼叫转移与呼叫前转
  16. 搜索技巧——奇偶剪纸
  17. npm install报错解决fatal: Unable to look up github.com (port 9418) npm ERR! exited with error code: 128
  18. win10 c语言 语音功能,win10系统自带录音功能在哪?windows10开启录音功能的方法-系统城...
  19. 4k显示服务器,远程服务器4k显示器
  20. MySQL42000错误

热门文章

  1. 注解 @TableField(exist = false) 注明非数据库字段属性
  2. 基于RBF函数的点云孔洞修补
  3. 微信公众号开发之获取用户列表和用户基本信息(五)
  4. OpenGL 2D贴图texture与着色器Shader
  5. IMEI号和MEID号
  6. Qt Tablewidget表格数据的导出和导入
  7. 二值图像的形态学处理
  8. (DCDC)CM3601降压型开关稳压器 60V,480KHz,0.5A
  9. linux如何安装vmtools工具
  10. 今天高兴,分享一个我亲自测试的网上赚钱方法......