Android MediaPlayer 基础简介
本文链接: 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 基础简介的更多相关文章
- Android MediaPlayer 播放音频
本文链接: Android MediaPlayer 播放音频 主要介绍使用MediaPlayer播放音频的方式.关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPla ...
- 005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介
005 01 Android 零基础入门 01 Java基础语法 01 Java初识 05 Eclipse简介 Eclipse是一款集成开发工具--IDE. 集成开发环境(IDE,Integrated ...
- 002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介
002 01 Android 零基础入门 01 Java基础语法 01 Java初识 02 Java简介 学习Java的基础语法 Java是一门编程语言,学习的逻辑其实和现实世界的语言是一样的,需要了 ...
- 第一部分 Android MediaPlayer 概述
[IT168 技术文档]本文主要介绍的是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的架构.对于Android这样一个完整又相对复杂的系统,一个MediaPlayer功能 ...
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
Android BLE与终端通信(二)--Android Bluetooth基础搜索蓝牙设备显示列表 摘要 第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟, ...
- Android零基础入门第19节:Button使用详解
原文:Android零基础入门第19节:Button使用详解 Button(按钮)是Android开发中使用非常频繁的组件,主要是在UI界面上生成一个按钮,该按钮可以供用户单击,当用户单击按钮时,按钮 ...
- Android零基础入门第18节:EditText的属性和使用方法
原文:Android零基础入门第18节:EditText的属性和使用方法 EditText与TextView非常相似,它甚至与TextView 共用了绝大部分XML属性和方法.EditText与Tex ...
- Android零基础入门第1节:Android的前世今生
原文:Android零基础入门第1节:Android的前世今生 现在网上有很多各色Android资料了,但相对来说还是比较零散,Android覆盖的范围极广,最近刚好有机会全部拉通整理一遍,也保存起来 ...
- Android零基础入门第82节:Activity数据回传
上一节学习了将简单的数据从MainActivity传递到SecondActivity,本节一起来学习数据如何从SecondActivity回传到MainActivity. 一.简介 前面己经提到,Ac ...
随机推荐
- 洛谷 P4124 [CQOI2016]手机号码
题意简述 求l~r之间不含前导零,至少有三个相邻的相同数字,不同时含有4和8的11位正整数的个数 题解思路 数位DP,注意在l,r位数不够时补至11位 代码 #include <cstdio&g ...
- 弃用 wget, 拥抱多线程下载 axel
0x00 事件 对于在 Linux 的下载工具而言,比较常用的就是 wget 或者 curl,吾也一直用 wget 的方式进行网络上的资源下载.偶然发现了 axel 这个支持多线程的下载工具,试用了几 ...
- UI 组件 | Toggle
Toggle(复选框)组件 Toggle 是一个 CheckBox,当它和 ToggleGroup 一起使用的时候,可以变成 RadioButton. 创建 Toggle 组件 层级管理器右击-> ...
- 线程学习oneday
进程:执行中的程序叫做进程(Process),是一个动态的概念. 线程:一个进程可以产生多个线程.同多个进程可以共享操作系统的某些资源一样,同一进程的多个线程也可以共享此进程的某些资源(比如:代码.数 ...
- 《MyCat分库分表策略详解》
在我们的项目发展到一定阶段之后,随着数据量的增大,分库分表就变成了一件非常自然的事情.常见的分库分表方式有两种:客户端模式和服务器模式,这两种的典型代表有sharding-jdbc和MyCat.所谓的 ...
- Liunx学习总结(二)--目录和文件管理
之前我们了解了什么是 liunx ,并且认识了它的目录结构,今天我们就来学习下如何进行目录和文件的管理. 创建目录 语法: mkdir [-mp] 目录名称 选项与参数 -m :配置文件的权限喔!直接 ...
- 10_switch语句的使用
/* switch 语句和c语言的用法不同 1.go语句是默认添加break语句的,但c不是默认的 2.go语句添加一个fallthrough语句,可以顺序执行接下来的结构 3.switch在关键词后 ...
- Docker Machine的使用
前面两篇文章(<Asp.Net Core 发布到 Docker(Linux Centos 虚拟机,使用Dockerfile)> <Docker Compose的使用>),简单介 ...
- 线程、进程的区别,Java的几个线程状态
线程.进程的区别 进程的定义:进程就是程序在一个数据集合上的一次执行过程.他与程序的区别在于程序是静态的代码,而进程是动态的执行过程. 进程的特性:1.结构性,进程由程序块.数据块.进程 ...
- 牛客小白月赛6 I 公交线路 最短路 模板题
链接:https://www.nowcoder.com/acm/contest/136/I来源:牛客网 题目描述 P市有n个公交站,之间连接着m条道路.P市计划新开设一条公交线路,该线路从城市的东站( ...