关于MediaPlayer的详细介绍
1)如何获得MediaPlayer实例:
可以使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
也可以使用create的方式,如:
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了
2) 如何设置要播放的文件:
MediaPlayer要播放的文件主要包括3个来源:
a. 用户在应用中事先自带的resource资源
例如:MediaPlayer.create(this, R.raw.test);
b. 存储在SD卡或其他文件路径下的媒体文件
例如:mp.setDataSource("/sdcard/test.mp3");
c. 网络上的媒体文件
例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");
MediaPlayer的setDataSource一共四个方法:
setDataSource (String path)
setDataSource (FileDescriptor fd)
setDataSource (Context context, Uri uri)
setDataSource (FileDescriptor fd, long offset, long length)
其中使用FileDescriptor时,需要将文件放到与res文件夹平级的assets文件夹里,然后使用:
AssetFileDescriptor fileDescriptor = getAssets().openFd("rain.mp3");
m_mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),fileDescriptor.getStartOffset(), fileDescriptor.getLength());
来设置datasource
Android提供了常见的音频、视频的编码、解码机制。借助于多媒体类MediaPlayer的支持,开发人员可以很方便在在应用中播放音频、视频。本篇博客主要讲解在Android平台下如何播放一个音频文件。
本篇博客主要内容如下:
- MediaPlayer
- MediaPlayer的音频源
- 使用MediaPlayer播放音乐
- MediaPlayer使用技巧
- Demo--一个简单的MP3播放器
MediaPlayer
上面提到过,Android下对于音频、视频的支持均需要使用到MediaPlayer,它主要用来控制Android下播放文件或流的类。MediaPlayer处于Android多媒体包下"android.media.MediaPlayer",仅有一个无参的构造函数,虽然仅为我们提供了一个无参的构造函数,为了方便我们初始化,还为我们提供了几个静态的create()方法用于完成MediaPlayer初始化的工作。
- static MediaPlayer create(Context context,int resid):通过音频资源的Id来创建一个MediaPlayer实例。
- static MediaPlayer create(Context context,Uri uri):通过一个音频资源的Uri地址来创建一个MediaPlayer实例。
MediaPlayer除了通过上面两个create()方法在初始化的时候指定媒体资源,还可以通过MediaPlayer.setDataSource()方法为初始化后的MediaPlayer设置媒体资源,setDataSource()具有多个重载函数,适用于不同的媒体资源来源,以下讲解几个常用的,其他的可以查阅官方文档。
- void setDataSource(String path):通过一个媒体资源的地址指定MediaPlayer的数据源,这里的path可以是一个本地路径,也可以是网络路径。
- void setDataSource(Context context,Uri uri):通过一个Uri指定MediaPlayer的数据源,这里的Uri可以是网络路径或这一个内容提供者的Uri。
- void setDataSource(FileDescriptor fd):通过一个FileDescriptor指定一个MediaPlayer的数据源。
MediaPlayer的音频源
通过上面介绍的初始化MediaPlayer的播放时媒体数据源的方法可以看出,MediaPlayer支持的数据源有:本地文件、内部的Uri(内容提供者)、外部Uri。
如,设置一个本地SD卡的资源:
1.1 mediaPlayer = new MediaPlayer();2.2 mediaPlayer.setDataSource("/sdcarc/a.mp3");注意读内存卡,还需要设定访问内存卡的权限:
1.<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>如,设置一个外部uri的网络流媒体资源:
1.1 mediaPlayer = new MediaPlayer();2.2 mediaPlayer.setDataSource(http://192.168.1.102:1231/music/a.mp3);如果访问网络流媒体资源,还需要设置访问网络的权限:
1.<uses-permission android:name="android.permission.INTERNET"></uses-permission>使用MediaPlayer播放音乐
MediaPlayer其实是一个封装的很好的音频、视频流媒体操作类,如果查看其源码,会发现其内部是调用的native方法,所以它其实是有C++实现的。
既然是一个流媒体操作类,那么必然涉及到,播放、暂停、停止等操作,实际上MediaPlayer也为我们提供了相应的方法来直接操作流媒体。
- void statr():开始或恢复播放。
- void stop():停止播放。
- void pause():暂停播放。
通过上面三个方法,只要设定好流媒体数据源,即可在应用中播放流媒体资源,为了更好的操作流媒体,MediaPlayer还为我们提供了一些其他的方法,这里列出一些常用的,详细内容参阅官方文档。
- int getDuration():获取流媒体的总播放时长,单位是毫秒。
- int getCurrentPosition():获取当前流媒体的播放的位置,单位是毫秒。
- void seekTo(int msec):设置当 前MediaPlayer的播放位置,单位是毫秒。
- void setLooping(boolean looping):设置是否循环播放。
- boolean isLooping():判断是否循环播放。
- boolean isPlaying():判断是否正在播放。
- void prepare():同步的方式装载流媒体文件。
- void prepareAsync():异步的方式装载流媒体文件。
- void release ():回收流媒体资源。
- void setAudioStreamType(int streamtype):设置播放流媒体类型。
- void setWakeMode(Context context, int mode):设置CPU唤醒的状态。
- setNextMediaPlayer(MediaPlayer next):设置当前流媒体播放完毕,下一个播放的MediaPlayer。
大部分方法的看方法名就可以理解,但是有几个方法需要单独说明一下。
在使用MediaPlayer播放一段流媒体的时候,需要使用prepare()或prepareAsync()方法把流媒体装载进MediaPlayer,才可以调用start()方法播放流媒体。
setAudioStreamType()方法用于指定播放流媒体的类型,它传递的是一个int类型的数据,均以常量定义在AudioManager类中, 一般我们播放音频文件,设置为AudioManager.STREAM_MUSIC即可。
除了上面介绍的一些方法外,MediaPlayer还提供了一些事件的回调函数,这里介绍几个常用的:
- setOnCompletionListener(MediaPlayer.OnCompletionListener listener):当流媒体播放完毕的时候回调。
- setOnErrorListener(MediaPlayer.OnErrorListener listener):当播放中发生错误的时候回调。
- setOnPreparedListener(MediaPlayer.OnPreparedListener listener):当装载流媒体完毕的时候回调。
- setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener listener):当使用seekTo()设置播放位置的时候回调。
MediaPlayer使用技巧
在使用MediaPlayer的使用过程中,有个小技巧需要说明一下:
1、在使用start()播放流媒体之前,需要装载流媒体资源。这里最好使用prepareAsync()用异步的方式装载流媒体资源。因为流媒体资源的装载是会消耗系统资源的,在一些硬件不理想的设备上,如果使用prepare()同步的方式装载资源,可能会造成UI界面的卡顿,这是非常影响用于体验的。因为推荐使用异步装载的方式,为了避免还没有装载完成就调用start()而报错的问题,需要绑定MediaPlayer.setOnPreparedListener()事件,它将在异步装载完成之后回调。异步装载还有一个好处就是避免装载超时引发ANR((Application Not Responding)错误。
01.1 mediaPlayer = new MediaPlayer();02.2 mediaPlayer.setDataSource(path);03.3 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);04.4 05.5 // 通过异步的方式装载媒体资源06.6 mediaPlayer.prepareAsync();07.7 mediaPlayer.setOnPreparedListener(new OnPreparedListener() { 08.8 @Override09.9 public void onPrepared(MediaPlayer mp) {10.10 // 装载完毕回调11.11 mediaPlayer.start();12.12 }13.13 });2、使用完MediaPlayer需要回收资源。MediaPlayer是很消耗系统资源的,所以在使用完MediaPlayer,不要等待系统自动回收,最好是主动回收资源。
1.1 if (mediaPlayer != null && mediaPlayer.isPlaying()) {2.2 mediaPlayer.stop();3.3 mediaPlayer.release();4.4 mediaPlayer = null;5.5 }3、使用MediaPlayer最好使用一个Service来使用,并且在Service的onDestory()方法中回收MediaPlayer资源,实际上,就算是直接使用Activity承载MediaPlayer,也最好在销毁的时候判断一下MediaPlayer是否被回收,如果未被回收,回收其资源,因为底层调用的native方法,如果不销毁还是会在底层继续播放,而承载的组件已经被销毁了,这个时候就无法获取到这个MediaPlayer进而控制它。
01.1 @Override02.2 protected void onDestroy() {03.3 if (mediaPlayer != null && mediaPlayer.isPlaying()) {04.4 mediaPlayer.stop();05.5 mediaPlayer.release();06.6 mediaPlayer = null;07.7 }08.8 super.onDestroy();09.9 }4、对于单曲循环之类的操作,除了可以使用setLooping()方法进行设置之外,还可以为MediaPlayer注册回调函数,MediaPlayer.setOnCompletionListener(),它会在MediaPlayer播放完毕被回调。
01.1 // 设置循环播放02.2 // mediaPlayer.setLooping(true);03.3 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {04.4 05.5 @Override06.6 public void onCompletion(MediaPlayer mp) {07.7 // 在播放完毕被回调08.8 play(); 09.9 }10.10 });5、因为MediaPlayer一直操作的是一个流媒体,所以无可避免的可能一段流媒体资源,前半段可以正常播放,而中间一段因为解析或者源文件错误等问题,造成中间一段无法播放问题,需要我们处理这个错误,否则会影响Ux(用户体验)。可以为MediaPlayer注册回调函数setOnErrorListener()来设置出错之后的解决办法,一般重新播放或者播放下一个流媒体即可。
1.1 mediaPlayer.setOnErrorListener(new OnErrorListener() {2.2 3.3 @Override4.4 public boolean onError(MediaPlayer mp, int what, int extra) {5.5 play();6.6 return false;7.7 }8.8 });Demo--一个简单的MP3播放器
上面已经介绍了MediaPlayer播放一段音频文件的所有需要用到的内容。下面通过一个简单的Demo来演示如何使用MediaPlayer播放一个SD卡上的MP3文件。操作MediaPlayer应该放在Service中完成,这里为了简单,使用Activity直接操作MediaPlayer。代码注释里写的很清楚里,这里不再累述。
执行这个示例需要在/sdcard/目录下存在xm.mp3的文件。
001.1 package cn.bgxt.mediaplayerdemo;002.2003.3 import java.io.File;004.4 import android.media.AudioManager;005.5 import android.media.MediaPlayer;006.6 import android.media.MediaPlayer.OnCompletionListener;007.7 import android.media.MediaPlayer.OnErrorListener;008.8 import android.media.MediaPlayer.OnPreparedListener;009.9 import android.os.Bundle;010.10 import android.app.Activity;011.11 import android.view.View;012.12 import android.widget.Button;013.13 import android.widget.EditText;014.14 import android.widget.Toast;015.15016.16 public class MainActivity extends Activity {017.17 private EditText et_path;018.18 private Button btn_play, btn_pause, btn_replay, btn_stop;019.19 private MediaPlayer mediaPlayer;020.20021.21 @Override022.22 protected void onCreate(Bundle savedInstanceState) {023.23 super.onCreate(savedInstanceState);024.24 setContentView(R.layout.activity_main);025.25026.26 et_path = (EditText) findViewById(R.id.et_path);027.27 btn_play = (Button) findViewById(R.id.btn_play);028.28 btn_pause = (Button) findViewById(R.id.btn_pause);029.29 btn_replay = (Button) findViewById(R.id.btn_replay);030.30 btn_stop = (Button) findViewById(R.id.btn_stop);031.31032.32 btn_play.setOnClickListener(click);033.33 btn_pause.setOnClickListener(click);034.34 btn_replay.setOnClickListener(click);035.35 btn_stop.setOnClickListener(click);036.36 }037.37038.38 private View.OnClickListener click = new View.OnClickListener() {039.39040.40 @Override041.41 public void onClick(View v) {042.42043.43 switch (v.getId()) {044.44 case R.id.btn_play:045.45 play();046.46 break;047.47 case R.id.btn_pause:048.48 pause();049.49 break;050.50 case R.id.btn_replay:051.51 replay();052.52 break;053.53 case R.id.btn_stop:054.54 stop();055.55 break;056.56 default:057.57 break;058.58 }059.59 }060.60 };061.61 /**062.62 * 播放音乐063.63 */064.64 protected void play() {065.65 String path = et_path.getText().toString().trim();066.66 File file = new File(path);067.67 if (file.exists() && file.length() > 0) {068.68 try {069.69 mediaPlayer = new MediaPlayer();070.70 // 设置指定的流媒体地址071.71 mediaPlayer.setDataSource(path);072.72 // 设置音频流的类型073.73 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);074.74075.75 // 通过异步的方式装载媒体资源076.76 mediaPlayer.prepareAsync();077.77 mediaPlayer.setOnPreparedListener(new OnPreparedListener() {078.78 @Override079.79 public void onPrepared(MediaPlayer mp) {080.80 // 装载完毕 开始播放流媒体081.81 mediaPlayer.start();082.82 Toast.makeText(MainActivity.this, "开始播放", 0).show();083.83 // 避免重复播放,把播放按钮设置为不可用084.84 btn_play.setEnabled(false);085.85 }086.86 });087.87 // 设置循环播放088.88 // mediaPlayer.setLooping(true);089.89 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {090.90091.91 @Override092.92 public void onCompletion(MediaPlayer mp) {093.93 // 在播放完毕被回调094.94 btn_play.setEnabled(true);095.95 }096.96 });097.97098.98 mediaPlayer.setOnErrorListener(new OnErrorListener() {099.99100.100 @Override101.101 public boolean onError(MediaPlayer mp, int what, int extra) {102.102 // 如果发生错误,重新播放103.103 replay();104.104 return false;105.105 }106.106 });107.107 } catch (Exception e) {108.108 e.printStackTrace();109.109 Toast.makeText(this, "播放失败", 0).show();110.110 }111.111 } else {112.112 Toast.makeText(this, "文件不存在", 0).show();113.113 }114.114115.115 }116.116 /**117.117 * 暂停118.118 */119.119 protected void pause() {120.120 if (btn_pause.getText().toString().trim().equals("继续")) {121.121 btn_pause.setText("暂停");122.122 mediaPlayer.start();123.123 Toast.makeText(this, "继续播放", 0).show();124.124 return;125.125 }126.126 if (mediaPlayer != null && mediaPlayer.isPlaying()) {127.127 mediaPlayer.pause();128.128 btn_pause.setText("继续");129.129 Toast.makeText(this, "暂停播放", 0).show();130.130 }131.131132.132 }133.133 134.134 /**135.135 * 重新播放136.136 */137.137 protected void replay() {138.138 if (mediaPlayer != null && mediaPlayer.isPlaying()) {139.139 mediaPlayer.seekTo(0);140.140 Toast.makeText(this, "重新播放", 0).show();141.141 btn_pause.setText("暂停");142.142 return;143.143 } 144.144 play();145.145 }146.146 147.147 /**148.148 * 停止播放149.149 */150.150 protected void stop() {151.151 if (mediaPlayer != null && mediaPlayer.isPlaying()) {152.152 mediaPlayer.stop();153.153 mediaPlayer.release();154.154 mediaPlayer = null;155.155 btn_play.setEnabled(true);156.156 Toast.makeText(this, "停止播放", 0).show();157.157 }158.158159.159 }160.160161.161 @Override162.162 protected void onDestroy() {163.163 // 在activity结束的时候回收资源164.164 if (mediaPlayer != null && mediaPlayer.isPlaying()) {165.165 mediaPlayer.stop();166.166 mediaPlayer.release();167.167 mediaPlayer = null;168.168 }169.169 super.onDestroy();170.170 }171.171 }关于MediaPlayer的详细介绍的更多相关文章
- [No0000A7]批处理经常用到的变量及批处理>NUL详细介绍
绝对路径是指调用绝对的程序位置的路径,例如: start C:\Windows\test.exe 相对路径是文件改变路径以后还会按照变量的路径所在位置去调用,例如: start %WINDIR%\te ...
- linux配置网卡IP地址命令详细介绍及一些常用网络配置命令
linux配置网卡IP地址命令详细介绍及一些常用网络配置命令2010-- 个评论 收藏 我要投稿 Linux命令行下配置IP地址不像图形界面下那么方 便,完全需要我们手动配置,下面就给大家介绍几种配置 ...
- _MSC_VER详细介绍
_MSC_VER详细介绍 转自:http://www.cnblogs.com/braver/articles/2064817.html _MSC_VER是微软的预编译控制. _MSC_VER可以分解为 ...
- php CGI、Fastcgi、PHP-FPM的详细介绍与之间的关系
以下PHP CGI.Fastcgi.PHP-FPM的一些信息归纳和汇总----->详细介绍与之间的关系 一:CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的 web ...
- RabbitMQ消息队列(一): Detailed Introduction 详细介绍
http://blog.csdn.net/anzhsoft/article/details/19563091 RabbitMQ消息队列(一): Detailed Introduction 详细介绍 ...
- doT.js详细介绍
doT.js详细介绍 doT.js特点是快,小,无依赖其他插件. 官网:http://olado.github.iodoT.js详细使用介绍 使用方法:{{= }} for interpolati ...
- Linux截屏工具scrot用法详细介绍
Scrot是Linux命令行中使用的截图工具,能够进行全屏.选取等操作,下面小编将针对Scrot截图工具的用法给大家做个详细介绍,通过操作实例来学习Scrot的使用. 在Linux中安装Scrot ...
- Oracle Merge into 详细介绍
Oracle Merge into 详细介绍 /*Merge into 详细介绍MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句.通过MERGE语句,根据一张表或子查 ...
- cPage分页详细介绍
asp.net中各种数据控件,datalist.gridview.Repeater等分页是最常用的功能,几乎任何一个B/S项目,无论是系统还是网站都会用到.分页时,读取整个数据,直接绑定到控件,都可以 ...
随机推荐
- 4.用PHP打印出前一天的时间格式是2006-5-10 22:21:21
echo date('Y-m-d H:i:s', strtotime('-1 days'));
- Python数据
读取文件中数据的最高分数 highest_score=0 result_f=open("results.txt") for line in result_f: (name,scor ...
- iOS中Block的基础用法
本文简介 本章不会对Block做过多的实现研究.只是讲解基本的用法.纯粹基础知识.结合实际项目怎么去做举例.Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等.用过GCD就知道 ...
- c#下载网页源码的两种方法
1.WebClient: System.Net.WebClient wc = new System.Net.WebClient(); Byte[] pageData = wc.DownloadData ...
- [SDN] mininet walkthrough
本次学习使用的是mininet的VM-image,所以安装过程就先忽略掉了,主要学习使用方法. 同时完成了在虚拟机上配置minient和Wireshark, 可以直接在虚拟机上操作. 1. Every ...
- 基于Node的PetShop,oauth2认证RESTful API
前篇 - 基本认证,用户名密码 后篇 - OAuth2 认证 前文使用包passport实现了一个简单的用户名.密码认证.本文改用oauth2来实现更加安全的认证.全部代码在这里. OAUTH2 用户 ...
- DataGridView单元格美化
#region 重绘Column.Row int _RowHeadWidth = 41; /// /// 重绘Column.Row ...
- JQ写下拉列表项目移动(内附效果图和源代码)
效果图如下: 实现功能:点击第一个按钮,让选中的对象从左边移动到右边: 点击第二个按钮,让左边的所有对象移动到右边: 点击第三个按钮,让选中的对象从右边边移动到左边: 点击第四个按钮,让右边的所有 ...
- python打怪之路【第一篇】:99乘法表
需求:实现99乘法表 代码: #!/usr/bin/env python # -*- coding:utf-8 -*- #author chenjing for i in range(10): for ...
- python的异常小结与assert
异常的处理 一. 二. -----------------2016-4-20 18:04:06--