本文链接: 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. (十三)c#Winform自定义控件-导航菜单

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

  2. Redis总结(九)Linux环境如何安装redis

    以前总结Redis 的一些基本的安装和使用,由于是测试方便,直接用的window 版的reids,并没有讲redis在linux下的安装.今天就补一下Linux环境如何安装redis. 大家可以这这里 ...

  3. Oracle中的转换函数

    Oracle中的转换函数有三个,分别为to_char(),to_date(),to_number() 1.to_char()的用法 格式化当前的日期时间 select sysdate,to_char( ...

  4. Reactive 漫谈

    目录 概念 面向流设计 异步化 响应式宣言 参考文档 概念 Reactive Programming(响应式编程)已经不是一个新东西了. 关于 Reactive 其实是一个泛化的概念,由于很抽象,一些 ...

  5. linux 下 VSCODE 使用CMake编译STM32程序

    项目在做什么 项目地址 本项目是为了研究MCU在linux下开发而做的 --build 存放cmake编译生成的文件 --cmake 存放cmake编译时会用到的文件,比如工具链检查.编译选项等 -- ...

  6. SynchronousQueue队列程序的执行结果分析

    public static void main(String[] args) throws Exception { /** * SynchronousQueue队列程序的执行结果分析 * Blocki ...

  7. 图表控件业界革命 -Arction新产品LightningChart JS 上市

    芬兰高科技企业Arction Ltd 在今年8月份推出了用于网页的数据可视化控件新解决方案—— LightningChart JS. 初次的基准测试表明,该产品为网页应用程序的数据可视化刷新了新的纪录 ...

  8. Spark应用场景以及与hadoop的比较

    一.大数据的四大特征: a.海量的数据规模(volume) b.快速的数据流转和动态的数据体系(velocity) c.多样的数据类型(variety) d.巨大的数据价值(value) 二.Spar ...

  9. 设计模式(C#)——09外观模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321 前言       在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化,然 ...

  10. 09_if条件语句的使用

    1.条件语句是用来判断给定的条件是否满足(表达式值是否为0),并根据判断的结果(真或假)决定执行的语句2.go语言和C语言的条件语句在语法格式上大体相似,但是还是有略微的不同,具体的细节如下 例子:p ...