解读官方Android MediaPlayer API(1)

2023-05-16

public class MediaPlayer

extends Object

MediaPlayer class 能够用来使用来控制vudio/video(音频或视频)文件和流文件的播放.举个例子可以在

VideoView 中了解怎么样使用这些方法。请看Audio and Video 中附加的文档。

MedioPlayer状态图如下:

audio/video(音频/视频)文件和流的控制是通过状态机制管理的。以下图标显示了 MediaPlayer 对象在播

放控制操作支持下被执行的生命周期和状态。椭圆代表MedioPlayer对象可能驻留的状态。弧线代表播放控制

操作驱使对象的状态间的转换。这里有两种弧线类型。单箭头的弧线代表同步的方法调用,而双箭头的弧线代

表异步的方法调用。

从状态图,我们可以知道MedioPlayer对象有以下的状态:

1 ) 当使用new或调用reset()后MedioPlayer对象就会被创建,对象将处在Idle状态;并且当release()被调用后,

对象将处于End状态。 这两种状态之间是MedioPlayer对象的生命周期。

1.1) 这里有点微妙但又很重要的不同是在MedioPlayer对象的创建和创建并调用reset()之后的MedioPlayer对象中

在Idle状态时调用例如getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(),

setAudioStreamType(int) setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(int)

prepare() or prepareAsync() 这些方法,都编程的错误。在MediaPlayer对象被构建后如果这些方法被调用,框架将无法被

内部的播放引擎回调OnErrorListener.onError() 并且对象的状态不会改变。但如果MediaPlayer对象调用了reset()之后,调

用这些方法,内部的播放引擎将能够回调 OnErrorListener.onError()方法,并且对象会转入Error状态。

1.2)并且推荐一旦MediaPlayer不再使用,就立即调用release()方法那么内部播放引擎对这个MediaPlayer对象的关联将会立即释放资源。

资源包括单一的资源例如计算机加速硬件组件(可理解为只能够一个对象使用的资源),所以若没有调用release()方法可能会导致后面

的MediaPlayer对象无法使用这单一资源 从而退回到软件实现或运行失败,一旦MediaPlayer对象进入了End状态,它将不再被使

用,并且没有办法回到其他任何状态。

1.3)此外,使用new创建的MediaPlayer对象将处于Idle状态,然而那些通过重载的create()便利方法创建的MediaPlayer对象却不是出在Idle状态。

实际上,如果成功调用create()方法,那么这些对象将是处在Prepared状态。

2)通常,一些播放控制操作由于各种各样的原因而运行失败,例如 audio/video的格式不支持;缺少隔行扫描的audio/video;分表率太高;流超时等此类原因。

那么,错误的报告和恢复在这些情况下是重要的。有时,由于程序设计的错误,在一个无效的状态下调用一个播放控制操作也可能发生。在所有这些错误条件下,

内部的播放引擎会调用一个由客户端程序员提供的OnErrorListener.onError()方法。客户端程序员可以通过调用Medialayer.setOnErrorListener(android.media.

MediaPlayer.OnErrorListener)方法来注册OnErrorListener.

2.1)一旦错误发生,值得注意的是,MediaPlayer对象会进入Error状态,即使没有注册OnErrorListener,应用还是会进入Error状态。

2.2)为了重新使用在Error状态的MediaPlayer对象使它从Error状态恢复,那么reset()方法的调用能够恢复对象到Idle状态。

2.3)一个好的程序设计实践你的应用,是有注册一个OnErrorListener用来注意来自内部播放引擎的Error的通知。

2.4)在一个invalid状态下, 例如调用prepare(),   prepareAsync(),或者一个重写的setDataSource方法。IlleglStateException异常被抛出,可以防止程序设计的错误.。

3)调用setDataSource(FileDescriptor)方法,或setDataSource(String)方法,或setDataSource(Context,Uri)方法,

setDataSource(FileDescriptor,long,long)方法会使处于Idle状态的对象迁移到Initialized状态。

3.1)若当对象在任何一个其他状态下调用setDataSource()会抛出 IllegalStateException 异常。

3.2)好的编程习惯是不要疏忽了调用setDataSource()方法的时候可能会抛出的IllegalArgumentException异常和IOException异常。 

4)一个MedioPlayer对象在播放开始之前必须首先进入Prepared状态。

4.1)有两种方法(同步和异步)可以使MediaPlayer对象进入Prepared状态:要么调用prepare()方法(同步),

此方法返回就表示该MediaPlayer象已经进入了Prepared状态;要么调用prepareAsync()方法(异步),此方法会使此

MediaPlayer对象进入Preparing状态并返回,而内部的播放引擎会继续未完成的准备工作。当同步版本返回时或异步版本

的准备工作完全完成时就会调用客户端程序员提供的OnPreparedListener.onPrepared()监听方法。可以调MediaPlayer

.setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)方法来注册OnPreparedListener.

4.2)值得注意的是Preparing是个短暂的状态,在此状态下调用任何具备边影响的方法的结果都是未知的!

4.3)在任何其他状态下,调用prepare()prepareAsync()方法会抛出IllegalStateException异常。

4.4)当MediaPlayer对象处于Prepared状态的时候,可以调用相应的方法调整音频/视频的属性,如音量,

播放时是否一直亮屏,循环播放等。 

5)想要开始播放,start()必须需要调用。在start()成功的调用之后MediaPlayer 对象将进入 Started的状态,isPlaying()方法可

以被调用来测试某个MediaPlayer对象是否在Started状态。

5.1)当在 Started状态,内部播放引擎会调用客户端程序员提供的OnBufferingUpdateListener.onBufferingUpdate()回调方法,

通过setOnBufferingUpdateListener(OnBufferingUpdateListener)注册监听。此回调方法允许应用程序追踪流播放的缓冲的状态。

5.2)对一个已经处于Started 状态的MediaPlayer对象调用start()方法没有影响。

6)播放可以被暂停,停止,和调整当前的播放位置。当调用pause()方法并返回时,会使MediaPlayer对象进入Paused状态。

注意StartedPaused状态的相互转换在内部的播放引擎中是异步的。所以可能需要一点时间在isPlaying()方法中更新

状态,若在播放流内容,这段时间可能会有几秒钟。

6.1) 调用start()方法会让一个处于Paused状态的MediaPlayer对象从之前暂停的地方恢复播放。当调用start()方法

返回的时候,MediaPlayer对象的状态会又变成Started状态。


6.2) 对一个已经处于Paused状态的MediaPlayer对象pause()方法没有影响。

7) 调用stop()方法会停止播放,并且还会让一个处于StartedPausedPreparedPlaybackCompleted状态的MediaPlayer进入Stopped状态。

7.1)一旦MediaPlayer在Stopped状态,mediaPlayer不能开始播放,直到prepare() or prepareAsync()调用后,

使MediaPlayer再次进入Prepared状态之后。

7.2)对一个已经处于Stopped状态的MediaPlayer对象stop()方法没有影响。

8) 调用seekTo()方法可以调整播放的位置。

8.1)seekTo(int)方法是异步执行的,所以它可以马上返回,但是实际的定位播放操作可能需要一段时间才能完成,

尤其是播放流形式的音频/视频。当实际的定位播放操作完成之后,内部的播放引擎会调用客户端程序员提供的

OnSeekComplete.onSeekComplete()回调方法。可以通过setOnSeekCompleteListener(OnSeekCompleteListener)方法注册。

8.2)注意,seekTo(int)方法也可以在其它状态下调用,比如PreparedPausedPlaybackCompleted状态。

8.3)此外,目前的播放位置,实际可以调用getCurrentPosition()方法得到,它可以帮助如音乐播放器的应用程序不断更新播放进度

9) 当播放到流的末尾,播放就完成了。

9.1) 如果调用了setLooping(boolean)方法开启了循环模式,那么这个MediaPlayer对象会重新进入Started状态。



9.2) 若没有开启循环模式,那么内部的播放引擎会调用客户端程序员提供的OnCompletion.onCompletion()回调方法。

可以通过调用MediaPlayer.setOnCompletionListener(OnCompletionListener)方法来设置。内部的播放引擎一旦调

用了OnCompletion.onCompletion()回调方法,说明这个MediaPlayer对象进入了PlaybackCompleted状态。

9.3) 当处于PlaybackCompleted状态的时候,可以再调用start()方法来让这个MediaPlayer对象再进入Started状态。 

参考文献:

1.谷歌官方Android SDK开发文档

2.http://my.oschina.net/zhangqingcai/blog/29660

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解读官方Android MediaPlayer API(1) 的相关文章

  • Android 上的本地设备组的 Google Cloud Messaging (GCM) 给出 HTTP 错误代码 401

    我正在尝试让 Google Cloud Messaging GCM 在 Android 上与本地设备组一起使用 如上所述https developers google com cloud messaging android client d
  • 点击 FCM 通知消息时如何获取消息正文?

    当应用程序在后台时 通知消息是通过Notification传递的 当点击通知时 应用程序启动 我如何获取消息正文 意图是这样的 Bundle google sent time 1470813025421 from 568540028909
  • Android Volley NetworkDispatcher

    我的应用程序从网络服务加载大量数据 并且我正在使用 volley 库来处理网络请求 Volley 正在堆叠 NetworkDispatcher 对象并最终导致应用程序崩溃 我用DDMS堆转储进行了测试 http spragucm wordp
  • Clang PCH 性能比标头差?

    我在源文件中包含一组标头 这些标头很少 从未更改 解析 重新解析使用标头的频繁更改的源文件 IDE 用例 需要太长时间 几秒钟 作为提高性能的一种方式 我想使用 Clang PCH 请注意 我正在 Android 上以发布模式 99 确定
  • 将 timeout() 与 retryWhen() 结合起来

    我正在创建一个简单的应用程序 用于使用 RxAndroidBle 库连接蓝牙设备 干杯 大家干得好 我遇到的情况是 有时当我连接到设备时 我会收到状态为 133 的 Gatt 错误 我知道这可能会发生 所以我想做的就是在发生错误时重试所有操
  • Google Play Console - 管理第一个应用程序发布的发布

    根据通过托管发布控制何时发布应用程序更改 https support google com googleplay android developer answer 9859654 hl enPlay 管理中心帮助中的页面 托管发布仅适用于更
  • 对于 Android 开发,我可以在图像视图上使用 JPG 图像而不是 PNG 图像吗?

    这个问题的主要目的是了解考虑以下场景 在 Android 开发中选择 PNG 和 JPG 的最佳选择是什么 1 使用jpg图像作为背景是一个好的选择吗 2 与 png 相比 jpg 图像的加载时间会更长吗 3 与 png 相比 jpg 会花
  • 以编程方式切换进度条的颜色

    所以我有一个图层列表 其中包含一个具有形状和纯色的项目 现在我想在我的代码中更改这种颜色
  • Android + PhoneGap拦截URL(相当于iOS的shouldStartLoadWithRequest)

    我的 PhoneGap 包装的 本地托管的 Sencha Touch 应用程序会进行一些虚假的 URL 回调来与本机包装器进行通信 IE app callback do function a 在iOS中我实现了以下内容 BOOL webVi
  • 如果没有发生触摸事件,Android SurfaceView 会变慢

    我正在制作一款游戏 除了游戏循环之外一切都很顺利 我正在使用 SurfaceView 并绘制 2D Sprites 位图 目前游戏是一艘穿过小行星带的飞船 飞船停留在屏幕中央 手机向任一方向倾斜以移动小行星 小行星改变位置而不是玩家 当旧的
  • 当应用程序离开后台并在 iOS 和 Android 中返回时,WebView 正在重新加载?

    我有一个小应用程序 它仅包含一个网络视图 我正在使用 url 加载网络视图 但是当我的应用程序进入后台并返回时 网络视图正在重新加载 对我来说 这不应该发生 在 iOS 和 Android 中 当应用程序进入后台时 如何停止 webview
  • Android:如何使用“uses-library”?

    我的Android应用程序可以分为客户端UI层和API层 我想将它们部署为单独的 应用程序 以便可以重用 API 层 在 Eclipse 中 我将它们编写为 2 个独立的 Android 项目 在客户端 UI 项目中 我在其构建路径中声明
  • 待定意图的多个实例

    我创建了一个小部件 单击该小部件会激活 PendingIntent 问题是 当我屏幕上有多个小部件时 只有最新的小部件才会启动 PendingIntent 我读过一些关于独特请求代码的内容 但没有弄清楚这一点 有什么想法可以让多个小部件和
  • Android 上的 wifi 聊天

    Android 上可以使用 Wifi 聊天吗 我的要求是我的电脑与 wifi 适配器连接 并且我的 Android 设备有 wifi 我想将我的电脑转换为服务器 将 Android 设备转换为客户端并实现聊天 这可能吗 请帮帮我 显然这是可
  • 无法解析“:app@debug/compileClasspath”的依赖关系:无法解析

    新安装的安卓工作室3 1 3在创建新项目并第一次编译时出现奇怪的依赖关系错误 一个相似的question https stackoverflow com questions 46949622 android studio 3 0 unabl
  • Android模拟器相机自定义图像

    有谁知道模拟器相机启动时可以打开一些个人照片吗 我有一个基于图像分析的应用程序 我希望当我单击相机按钮时 相机会打开而不是默认的 Android 模拟器移动图像 我希望它打开一些我设置为默认图像的图像 因此 当我选择拍照时 它只会显示该图像
  • 将 compose 示例项目导入到 android studio 版本 4.2

    我正在尝试导入编写示例项目 https github com android compose samples 但我面临这个错误 Invalid injected android support version 202 7660 26 42
  • Kotlin 协程的现有 3 函数回调

    我有一个带有具体示例的一般性问题 我想在拍照时使用 Kotlin 协程魔法而不是 Android 中的回调地狱 manager openCamera cameraId object CameraDevice StateCallback ov
  • Google CSE REST API:v1 是否已弃用,是否有 v2?

    作为 google CSE API 的许多用户 我最近收到一封来自 Google Custom Search 的电子邮件 询问我 请迁移到 Custom Search Element API 2 0 我检查了文档 https develop
  • 如何检查设备是否可以通过有效的 WiFi 连接访问互联网?

    我指的是设备已连接到接入点但由于某种原因被阻止使用此 AP 访问互联网的情况 检查wifi是否启用 WifiManager wfManager WifiManager getSystemService Context WIFI SERVIC

随机推荐