Android -- 多媒体播放之MediaPlayer基础简介

article/2025/10/2 3:19:05

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官方文档获取更准确的介绍。




http://chatgpt.dhexx.cn/article/QXJoInr1.shtml

相关文章

网易雷火9.18笔试题

3小时的题 我迟到了1个小时&#xff0c;提前了40分钟润&#xff0c;花了1个小时20分钟&#xff08;中途有点其他事&#xff09;&#xff0c;a了2道&#xff0c;第三题没思路&#xff0c;第4题不想看&#xff0c;就这样吧 #include <iostream> using namespace std; int…

网易笔试题总结

var string string; var number 0; var bool true; console.log(number || string); console.log(number && string); console.log(bool || number); console.log(bool && number); 输出结果 如果换下string和num的位置呢 var string string1; var numbe…

网易2019笔试题

1.苹果分堆 计算累加小组成员数&#xff0c;结合二分查找&#xff0c;复杂度O( min(n, mlogn) ) package wangyi123;import java.util.Scanner;public class groupNum {public static void main(String[] args) {Scanner sc new Scanner(System.in);while (sc.hasNext()) {i…

2022-08-20-网易笔试题

写在前面 题目收集来源自网络&#xff0c;前四题是开发岗的&#xff0c;后四题是算法岗的&#xff0c;因为代码无处提交&#xff0c;不一定正确&#xff0c;就不贴出来了&#xff0c;这里只写一下我的思路吧~欢迎大家一起讨论~~ 1、 思路&#xff1a;因为最大1e9&#xff0c…

网易游戏策划笔试-20190404

1-7题为文案题&#xff08;答题时请勿参考其他作品&#xff09;&#xff0c;8-23题为数值系统题&#xff0c; 两个方向分别计算分数&#xff0c;最终选择分数更高的方向作为最终成绩&#xff0c;建议优先选择自己擅长或感兴趣的方向进行答题。 8、&#xff08;无需过程&#xf…

JESD204接口调试总结——JESD204+In-system-ibert

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 JESD204接口调试总结——JESD204In-system-ibert 前言IP核的设置IP核连线调试jtag界面总结 前言 之前我们在讲serdes的时候讲到了使用in-system-ibert来进行眼图的扫描&…

JESD204B IP核的配置与使用

一、JESD204 配置方式&#xff1a; Configuration 1、Transmit or Receive: 选择是作为接收机还是发射机 2、LFMC : 默认值 3、Number of lanes : 传输的通道数&#xff0c;根据实际需求选择 4、pattern&#xff1a;模式的选择&#xff0c;正常情况下两个都不选 5、clocki…

JESD204接口调试总结——Xilinx JESD204B IP testbench解析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 JESD204接口调试总结——Xilinx JESD204B IP testbench解析 IP核配置testbench工程部分代码解读 IP核配置 1、IP核为接收功能 2、LMFC buffer设定为最大 3、4条lane 4、sysre…

STC15W204S下载

一&#xff1a;所使用测试板。 为8管脚最小板&#xff0c; 二&#xff1a;工程新建。 一&#xff1a;keil c51。 2&#xff1a;新建main,加入工程。 测试程序&#xff1a; #include <reg52.h>//stc15w20s为51内核#define MAIN_Fosc 35000000UL //定义主时钟sbit PIN_LE…

JESD204B 系统复位与同步选项

CGS&#xff0c;代码组同步&#xff0c;ILA&#xff0c;初始化多帧序列帧同步&#xff0c;然后进行数据传输 。 系统复位 在系统复位上&#xff1a;JESD204中提供了一个全局的异步时钟复位&#xff0c;rx_reset用来复位整个系统&#xff0c;AXI4-Lite系统总线复位不受此影响&am…

Atsha204a使用心得

最近公司要用到Atsha204a做软件和硬件的绑定加密&#xff0c;于是就调了它的驱动&#xff0c;将使用过程中遇到的坑整理下&#xff0c;也好让各位同仁少加点班&#xff1b;废话少说&#xff0c;直接入正题。 0.加密原理&#xff1a; 主控端和Atsha204a端有相同的16 组密码&am…

JESD204B接口调试记录3 - 总结

目录 一、介绍下项目历史情况 二、为什么要用fs4模式&#xff1f; 三、为什么要将采样率改成2.5Gsps&#xff1f; 四、时钟芯片参数如何设置&#xff1f; 五、AD芯片参数如何设置&#xff1f; 六、FPGA工程里JESD204 IP如何设置&#xff1f; 七、传输层如何解包&#xff…

【JESD204B】基于JESD204B协议的ADC、DAC数据传输

1、JESD204协议概述 ADC、DAC技术即模数、数模转换技术&#xff0c;在军用和民用领域广泛应用&#xff0c;如现在常用的有微信语音、网络电话、其典型数据处理流程&#xff1a; 语音输入->ADC采样->调制->基站->无线传输->基站->解调->DAC->语音输出…

理解JESD204B链路参数 Understanding JESD204B Link Parameters

想要彻底理解参数意义要先看JESD协议标准原文&#xff0c;再看看这文章。这是我花了很久才意识到的道理&#xff0c;不过这篇文章对理解也有一定意义。 这个文章是我看的一篇英文文章的大体翻译&#xff0c;并不是逐行的。文章名《Understanding JESD204B Link Parameters》 L…

FPGA之JESD204B接口——总体概要 首片

1. 简介 JESD204是一种连接数据转换器&#xff08;ADC和DAC&#xff09;和逻辑器件的高速串行接口&#xff0c;该标准的 B 修订版支持高达 12.5 Gbps串行数据速率&#xff08;目前C修订版已经发布&#xff0c;即JESD204C&#xff09;&#xff0c;并可确保 JESD204 链路具有可重…

JESD204B 参数理解

M和N M表示单片芯片上转换器的个数。 N表示转换器的分辨率。 比如一个4通道14位的ADC器件&#xff0c;M为4&#xff0c;N为14. N’ N’ 定位为word 长度。N’的计算为首先把N打散成一个个的nibble,每个nibble为4bit.对于14bit和16bit的分辨率&#xff0c;都是4个nibble,12…

Atmel ATSHA204应用总结

1 ACES软件安装 Atmel Crypto Evaluation Studio (ACES) https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/Atmel%20Crypto%20%20Studio%20(ACES) 2 基本概念 ACES CE&#xff1a;Atmel Crypto Evalution Studio Configuration Environment&#xff08;基于加…

加密芯片ATSHA204之使用

目录 看手册Command PacketsConfiguration ZoneLock CommandNonce CommandGenDig CommandWrite CommandRead CommandMAC CommandDeriveKey Command相关参考 本文旨在记录 ATSHA204 的使用过程。ATSHA204 是一个安全认证和验证设备&#xff0c;可防止设备被抄袭&#xff0c;应该…

ATSHA204芯片手册阅读笔记

使用心得: &#xff08;1&#xff09;配置好IIC&#xff0c;访问芯片之前先唤醒。 &#xff08;2&#xff09;按个人需求配置好Config区域&#xff0c;配置好之后锁住Config。只有锁住了Config&#xff0c;才能去操作Data区。 &#xff08;3&#xff09;开始写数据区&#xff0…

JESD204标准概述

此篇是我在学习中做的归纳与总结&#xff0c;其中如果存在版权或知识错误请直接联系我&#xff0c;欢迎留言。 PS:本着知识共享的原则&#xff0c;此篇博客可以随意转载&#xff0c;但请标明出处&#xff01; 目录 JESD204协议标准的分类和区别&#xff1a; JESD204A JESD20…