本文链接: Android MediaPlayer 基础简介

简单介绍MediaPlayer的基本概念,状态,常用的方法与监听器。

什么是MediaPlayer

MediaPlayer类可以用来播放音视频文件,或者是音频流。开发者可以用它来播放本地音频,或者是网络在线音频。

MediaPlayer属于android.media包。

MediaPlayer的状态

播放控制由状态机控制。在日常生活中,我们常见的音频状态有播放中,暂停,停止,缓冲等等。

MediaPlayer的状态有如下几种:

  • Idle
  • End
  • Error
  • Initialized
  • Preparing
  • Prepared
  • Started
  • Stopped
  • Paused
  • PlaybackCompleted

状态的切换参考官方图例。

这里稍微解释一下状态转换图片。椭圆代表MediaPlayer可能停留的状态。椭圆之间的箭头表示方法调用,状态切换的方向。单箭头表示方法同步调用,双箭头表示异步调用。

从图中我们可以看出状态切换的路径和涉及到的方法。

Idle与End状态

当new一个MediaPlayer或者调用了reset方法,当前MediaPlayer会处于Idle状态。调用release后,会处于End状态。在这2个状态之间的状态可以看做是MediaPlayer对象的生命周期。

在新创建MediaPlayer和调用reset的MediaPlayer之间有一些细微的差别。

这两种情况都处于Idle状态,调用 getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioAttributes(android.media.AudioAttributes), setLooping(boolean), setVolume(float, float), pause(), start(), stop(), seekTo(long, int), prepare() 或 prepareAsync()方法都会抛出错误,如果是新实例化的MediaPlayer,不会回调 OnErrorListener.onError();但如果是reset后的MediaPlayer,会回调 OnErrorListener.onError()并且转换到Error状态。

如果MediaPlayer对象不再使用了,立即调用release()方法,释放内部播放器占用的资源。这些资源可能是唯一的,比如硬件加速组件。如果调用release失败,可能会引起一连串的MediaPlayer实例失效。当MediaPlayer处于End状态,它就不能再转移到其它状态了。

new一个MediaPlayer,处于Idle状态。如果用create方法创建实例,当创建完成时处于Prepared状态。

发生错误

一些情形可能会让MediaPlayer操作失败,比如不支持的音视频格式,分辨率过高,网络超时等等。

因此在这些情形下错误处理和恢复非常重要。有时候编程错误也会导致MediaPlayer操作错误。

开发者可以设置错误监听器setOnErrorListener(android.media.MediaPlayer.OnErrorListener)。当错误发生时,会调用用户实现的OnErrorListener.onError()方法。

不管有没有设置监听器,错误发生时MediaPlayer会进入Error状态。

为了重复使用同一个MediaPlayer对象,可以使用reset()方法把它从Error状态恢复到Idle状态。

设置错误监听器OnErrorListener是一个好的编程习惯。开发者可以监听到播放引擎的错误通知。

有时候会抛出IllegalStateException异常,比如在错误的状态调用了prepare(), prepareAsync()方法,或是setDataSource方法。

设置音源 setDataSource

调用setDataSource(java.io.FileDescriptor), 或者 setDataSource(java.lang.String), 或者 setDataSource(android.content.Context, android.net.Uri), 或者 setDataSource(java.io.FileDescriptor, long, long), 或者 setDataSource(android.media.MediaDataSource) 可以将MediaPlayer的状态从Idle转到Initialized状态。

如果在Idle状态之外的状态调用了setDataSource(),会抛出IllegalStateException异常。

开发者应该留意setDataSource方法抛出的IllegalArgumentException和IOException异常。

播放音频前必须在Prepared状态

MediaPlayer在开始播放音频前必须处于Prepared状态。

MediaPlayer有同步和异步2种方式来进入Prepared状态。如果是异步的方式,会先转到Preparing状态,再转到Prepared状态。

当准备完成时,内部的播放引擎会回调用户之前设置的OnPreparedListener的onPrepared()方法。

开发者必须注意的是,Preparing状态是一个过渡状态(transient state)。

处于Prepared状态时,可以通过相对应的方法设置音量,屏幕常亮,播放循环等。

开始播放

播放音频必须调用start()方法。调用start()返回成功后,MediaPlayer处于Started状态。

可以通过isPlaying()来判断当前是否在Started状态。

如果开发者设置了OnBufferingUpdateListener,Android内部播放器会向外传递buffer信息。

如果当前处于Started状态,再调用start()方法没有效果。

暂停播放与继续播放

音频可以被暂停播放和继续播放,也可以调整播放的位置。通过pause()方法来暂停音频播放。

成功调用pause()方法后,MediaPlayer进入Paused状态。

应当注意的是,MediaPlayer在Started状态与Paused状态之间切换是异步的。播放音频流的时候,这个转换过程可能会需要几秒钟。

MediaPlayer暂停时,start()方法可以从暂停的位置继续播放。成功调用start方法后会进入Started状态。

处于Paused状态时,调用pause()方法没有效果。

停止

调用stop()方法让MediaPlayer从Started, Paused, Prepared 或 PlaybackCompleted 状态进入 Stopped 状态。

在Stopped状态时,必须先调用prepare() 或 prepareAsync()进入Prepared状态后,才能播放音频。

处于Stopped状态时,调用stop()方法没有效果。

调整播放位置

调用seekTo(long, int)来调整播放位置。

seekTo(long, int)是一个异步方法,虽然它能立刻返回,但实际的位置调整可能会消耗一段时间,特别是在播放音频流的时候。当实际播放位置调整后,内部播放器会回调开发者设置的OnSeekComplete.onSeekComplete()。

在Prepared, Paused 和 PlaybackCompleted状态中,都可以调用seekTo方法。

可以通过getCurrentPosition()方法来获取当前播放位置。开发者可以得知当前播放的进度等等。

播放完毕

音频播放完成后,播放完毕。

如果调用setLooping(boolean)为true,MediaPlayer会停留在Started状态。

如果setLooping为false,内部播放器会调用开发者设置的OnCompletion.onCompletion(),并且进入PlaybackCompleted状态。

处于PlaybackCompleted状态时,调用start()方法可以从头开始播放音频。

常用监听器

开发者可以设置一些监听器,监听MediaPlayer的状态,错误事件等等。开发者应在同一个线程中创建MediaPlayer与设置的监听器。

setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)

监听MediaPlayer准备完成。一般与prepareAsync配合使用。

setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener)

获知video大小或video大小改变时的监听。

setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener)

监听调整位置完成。

setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener)

播放完成。

mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
// 当前播放完毕
}
});

setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener)

监听缓冲进度。在播放网络音频时常用。

缓冲监听器OnBufferingUpdateListener

    mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// 例如在这里更新UI
}
});

setOnInfoListener(android.media.MediaPlayer.OnInfoListener)

监听普通信息或者警告信息。

setOnErrorListener(android.media.MediaPlayer.OnErrorListener)

监听错误信息。错误发生时,可以在这里处理错误。

mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
LogUtil.e(TAG_PREFIX + " onERR i = " + i + " i1 = " + i1);
return true; // 返回true表示在此处理错误,不会回调onCompletion
}
});

注意onError的返回值。可以选择自己处理error。

         * @return True if the method handled the error, false if it didn't.
* Returning false, or not having an OnErrorListener at all, will
* cause the OnCompletionListener to be called.
*/
boolean onError(MediaPlayer mp, int what, int extra);

需要的权限

播放网络音频时需要Manifest.permission.INTERNET权限。

Android MediaPlayer 基础简介的更多相关文章

  1. Android MediaPlayer 播放音频

    本文链接: Android MediaPlayer 播放音频 主要介绍使用MediaPlayer播放音频的方式.关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPla ...

  2. 005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介

    005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介 Eclipse是一款集成开发工具--IDE. 集成开发环境(IDE,Integrated ...

  3. 002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介

    002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介 学习Java的基础语法 Java是一门编程语言,学习的逻辑其实和现实世界的语言是一样的,需要了 ...

  4. 第一部分 Android MediaPlayer 概述

    [IT168 技术文档]本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.对于Android这样一个完整又相对复杂的系统,一个MediaPlayer功能 ...

  5. Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表

    Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...

  6. Android零基础入门第19节:Button使用详解

    原文:Android零基础入门第19节:Button使用详解 Button(按钮)是Android开发中使用非常频繁的组件,主要是在UI界面上生成一个按钮,该按钮可以供用户单击,当用户单击按钮时,按钮 ...

  7. Android零基础入门第18节:EditText的属性和使用方法

    原文:Android零基础入门第18节:EditText的属性和使用方法 EditText与TextView非常相似,它甚至与TextView 共用了绝大部分XML属性和方法.EditText与Tex ...

  8. Android零基础入门第1节:Android的前世今生

    原文:Android零基础入门第1节:Android的前世今生 现在网上有很多各色Android资料了,但相对来说还是比较零散,Android覆盖的范围极广,最近刚好有机会全部拉通整理一遍,也保存起来 ...

  9. Android零基础入门第82节:Activity数据回传

    上一节学习了将简单的数据从MainActivity传递到SecondActivity,本节一起来学习数据如何从SecondActivity回传到MainActivity. 一.简介 前面己经提到,Ac ...

随机推荐

  1. 002——Netty之Netty介绍

    Netty出现背景 Java NIO难用 据说存在bug 业界其他NIO框架不成熟 Netty主要解决两个相应关注领域 (1)异步和事件驱动的实现. (2)一组设计模式,将应用逻辑与网络层解耦. 特性 ...

  2. (三十二)c#Winform自定义控件-表格

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  3. turtle绘制图形

    Example1: import turtle as t #初始设置画笔的宽度(size).颜色(color) t.pensize(5) t.pencolor("black") # ...

  4. [Spring cloud 一步步实现广告系统] 21. 系统错误汇总

    广告系统学习过程中问题答疑 博客园 Eureka集群启动报错 Answer 因为Eureka在集群启动过程中,会连接集群中其他的机器进行数据同步,在这个过程中,如果别的服务还没有启动完成,就会出现Co ...

  5. 利用ShardingSphere-JDBC实现分库分表

    利用ShardingSphere-JDBC实现分库分表 1. ShardingSphere概述 1.1 概述 业务发展到一定程度,分库分表是一种必然的要求,分库可以实现资源隔离,分表则可以降低单表数据 ...

  6. 使用 Docker Compose 快速构建 TiDB 集群

    本文档介绍如何在单机上通过 Docker Compose 快速一键部署一套 TiDB 测试集群.Docker Compose 可以通过一个 YAML 文件定义多个容器的应用服务,然后一键启动或停止. ...

  7. 算法与数据结构基础 - 贪心(Greedy)

    贪心基础 贪心(Greedy)常用于解决最优问题,以期通过某种策略获得一系列局部最优解.从而求得整体最优解. 贪心从局部最优角度考虑,只适用于具备无后效性的问题,即某个状态以前的过程不影响以后的状态. ...

  8. Asp.net MVC 集成AD域认证

    1.首先WebApi 应用下Web.config要配置域认证服务器节点,如下 <!--LDAP地址 用于项目AD系统账号密码验证--> <!--0:关闭域认证:1:开启域认证--&g ...

  9. 【selenium】- selenium简介

    本文由小编根据慕课网视频亲自整理,转载请注明出处和作者. 1. Selenium的来历 2. Selenium家庭成员 Selenium RC: Selenium 1 Selenium Webdriv ...

  10. Codeforces Round #503 (by SIS, Div. 2) D. The hat -交互题,二分

    cf1020D 题意: 交互题目,在有限的询问中找到一个x,使得数列中的第x位和第(x+n/2)位的值大小相同.数列保证相邻的两个差值为1或-1: 思路: 构造函数f(x) = a[x] - a[x ...