转载自
Android MediaPlayer使用方法简单介绍
播放音频
android中播放音频可以使用MediaPlayer类来实现,一下是它的一些方法:
方法名 功能描述
setDataSource() 设置要播放的音频文件的位置。
prepare() 在开始播放之前调用这个方法完成准备工作。
start() 开始或继续播放音频。
pause() 暂停播放音频。
reset() 将 MediaPlayer 对象重置到刚刚创建的状态。
seekTo() 从指定的位置开始播放音频。
stop() 停止播放音频。调用这个方法后的 MediaPlayer 对象无法再播放音频。
release() 释放掉与 MediaPlayer 对象相关的资源。
isPlaying() 判断当前 MediaPlayer 是否正在播放音频。
getDuration() 获取载入的音频文件的时长。
m_mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),fileDescriptor.getStartOffset(), fileDescriptor.getLength());
seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。
1、创建MediaPlayer实例
有两种创建MediaPlayer实例的办法,
办法1:
MediaPlayer player = MediaPlayer.Create(this, Resource.Raw.test);
用MediaPlayer.Create创建实例时可直接指定数据源。
办法2:
MediaPlayer player = new MediaPlayer();
2、数据源
有3种。
(1)播放raw文件夹下的资源文件
应用程序自带的音乐资源一般保存到raw文件夹下,下面的代码演示了如何播放Resource/raw下的媒体文件:
MediaPlayer mPlayer=MediaPlayer.Create(this, Resource.Raw.MyAudio);
mPlayer.Start();
注意:这种方式主要适用于播放应用程序自带的容量较小的资源文件,例如接听电话时播放的音乐、按键音、开机启动音、信息提示音等都可以随应用程序一块发布。
(2)播放来自文件系统的媒体文件
指播放Android默认的系统标准文件夹下、Assets文件夹下、SD卡中的媒体文件,这些文件都属于文件系统。
以下描述了使用MediaPlayer从文件系统中播放音频的步骤:
- 初始化MediaPlayer对象。
- 通过SetDataSource方法(同步方式)或者SetDataSourceAsync方法(异步方式)设置要播放的文件。
- 调用Prepare方法(同步方式)或者PrepareAsync方法(异步方式)初始化播放器。
- 调用Start方法开始音频播放。
- 注意采用这种方式时,播放顺序非常重要:先设置数据源、同步播放设备,最后再调用Start方法播放。
利用MediaPlayer与surfaceView相结合实现视频播放的效果
加载本地资源
/**加载本地资源 * 主要步骤: * 1.创建MediaPlayer播放器 * 1.MediaPlayer.create(this,"本地资源文件"); * 2.得到SurfaceHolder对象,surfaceView.getHolder() * 3.surfaceHolder绑定生命周期 surfaceHodler.addCallBack(new CallBack(){...}) * 4.在surfaceHolder监听的回调里面,与视频播放器进行绑定(surfaceCreated) * mediaPlayer.setDisplay(surfaceHolder) * 5.视频播放器播放视频 * mediaPlayer.start(); */
加载网络资源
/** * 加载网络资源 *主要步骤: * 1.创建MediaPlayer播放器 * new MediaPlayer(); * 2.设置数据源 * mediaPlayer.setDataSource(context,uri); * // meidaPlayer.setDataSource(path) * 3. .得到SurfaceHolder对象,surfaceView.getHolder() * 4.surfaceHolder绑定生命周期 surfaceHodler.addCallBack(new CallBack(){...}) * 5.在surfaceHolder监听的回调里面,与视频播放器进行绑定(surfaceCreated) * mediaPlayer.setDisplay(surfaceHolder) * 6.准备 * mediaPlayer.prepareAsync()//异步准备 * mediaPlayer.prepare()//同步准备 * 7.设置准备监听器 * mediaPlayer.setOnPreparedListener(new PreparedListener(){}); * 8.在准备监听器里开启mediaPlayer * mediaPlayer.start(); * * * //注意:
1.加载网络资源出现了bug,原因:设置异步准备时,会调用准备监听器来开启媒体播放器,同时主线程也会继续执行,通过播放器获取时长时,会出现媒体播放器无效的错误,因为播放器还没有开启播放.
解决:将异步准备后的操作都放在准备监听里面实现,
2.meidiaPlayer调用stop方法后可以再次播放视频,但需要用reset让meidiaPlayer对象回到初始状态,再重新设置资源 * */
xml:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="fanggao.qf.surfaceview_vedioplayer.MainActivity"> <FrameLayout android:id="@+id/fl_layout" android:layout_width="match_parent" android:layout_height="300dp"> <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="300dp" /> <ImageView android:id="@+id/iv_play" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@android:drawable/ic_media_play"/> </FrameLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:layout_below="@id/fl_layout"> <ImageView android:id="@+id/iv_play_controll" android:layout_width="wrap_content" android:layout_height="match_parent" android:src="@android:drawable/ic_media_play"/> <SeekBar android:id="@+id/sb_progress" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <TextView android:id="@+id/tv_time" android:layout_width="wrap_content" android:layout_height="match_parent" android:text="00:00:00/00:00:00" android:gravity="center_vertical"/> </LinearLayout> </RelativeLayout>
案列分析:
/** * 1.初始化控件 * 0.初始化媒体播放器 * 1.准备资源,并创建播放器 * 1.找到surfaceView,并创建生命周期 * 1.创建surfaceView * 1.surfaceView跟视频播放控件绑定 * 2.销毁surfaceView * 释放资源 * 2.播放图标显示 * 3.控制台显示播放图标 * 2.初始化事件 * 1.点击播放按钮-变为播放 * 1.当前播放按钮隐藏 * 2.控制条显示暂停图标 * 3.视频开始播放 * * 2.点击控制台 * 1.点击播放 * 1.控制台显示暂停图标 * 2.隐藏当前的播放按钮 * 3.视频开始播放 * 2.点击暂停 * 1.控制台按钮显示播放图标 * 2..当前播放按钮显示 * 3.视频暂停播放 * 3.拖到进度条 * 1.跳到对应的位置播放 * 2.更新时间 * * 3.初始化动态视图 * 2.更新控制台显示 * 1..拿到视频总长度 * 1.开启线程 * 1.更新seekBar进度 * 1.拿到当前进度 * 2.计算当前seekBar的值 * 3.发送到主线程 * 4.更新 * 1.更新seekBar的值 * 2.更新时间进度 * 1s更新一次 * 3.播放完成设置监听 * 4.释放资源 */
源代码:
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback,View.OnClickListener,SeekBar.OnSeekBarChangeListener,MediaPlayer.OnCompletionListener{ /*显示视频资源*/ private SurfaceView surfaceView; /*拖动条显示当前进度*/ private SeekBar sb_progress; /*surface的控制器,用来操纵surfaceView。处理它的Canvas上画的效果和动画,控制表面,大小,像素等。*/ private SurfaceHolder holder; /*媒体播放器播放音频*/ private MediaPlayer mediaPlayer; //显示暂停播放图标 private ImageView imgPlay; //控制台显示暂停播放图标 private ImageView imgControll; /*视频总长度*/ private int duration; /*handler发送的成功的标识*/ private final int UPDATE_PROGRESS = 0; /*让线程开始和结束的标记*/ private boolean flag; /*设置显示的图片*/ private TextView tvTime; /*更新进度条和时间*/ private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case UPDATE_PROGRESS: int currentPosition = (int) msg.obj; Log.i("tag", "handleMessage: "+currentPosition); //更新seekBar sb_progress.setProgress(currentPosition); //更新时间 updateTime(currentPosition,duration); break; default: break; } } }; private UpdateThread updateThread; /** * 更新时间 * @param currentPosition * @param duration */ private void updateTime(int currentPosition, int duration) { tvTime.setText(formatTime(currentPosition)+"/"+formatTime(duration)); } /** * 格式化时间 * @param time * @return */ private String formatTime(int time) {//格式化时间为00:00:00 //两位数,小于两位数自动补0 例 09:09:00 String format = "%02d:%02d:%02d"; //time为ms int hour = time/1000/3600; int minute = time/1000%3600/60; int second = time/1000%60; return String.format(format,hour,minute,second); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化视频资源 mediaPlayer =MediaPlayer.create(this,R.raw.hello); initView(); initEvent(); //获取视频的总长度(ms) duration = mediaPlayer.getDuration(); //为seekBar设置初始值 sb_progress.setMax(duration); } /** * 进度条拖动监听 * @param seekBar * @param progress * @param fromUser */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { //播放器跳到对应位置 mediaPlayer.seekTo(seekBar.getProgress()); } /** * 播放完成的时候监听 * @param mp */ @Override public void onCompletion(MediaPlayer mp) { //重置 int position = 0; //让视频跳到最开始并暂停 mp.seekTo(position); Message obtain = Message.obtain(); obtain.what = UPDATE_PROGRESS; obtain.obj = position; handler.sendMessage(obtain); imgPlay.setVisibility(View.VISIBLE); imgControll.setImageResource(android.R.drawable.ic_media_play); } class UpdateThread extends Thread{ @Override public void run(){ while(flag){ //获得当前的进度 int currentPosition = mediaPlayer.getCurrentPosition(); Message message = Message.obtain(); message.what = UPDATE_PROGRESS; //计算seekbar的值 message.obj = currentPosition; //handler发送进度 handler.sendMessage(message); //1s一次 SystemClock.sleep(1000); } } } private void initEvent() { //暂停按钮点击监听,点击播放视频或者暂停视频 imgControll.setOnClickListener(this); imgPlay.setOnClickListener(this); //拖动监听,跳到对应的位置 sb_progress.setOnSeekBarChangeListener(this); //播放完成监听,重置播放器,进度 mediaPlayer.setOnCompletionListener(this); } private void initView() { surfaceView = (SurfaceView) findViewById(R.id.surfaceView); sb_progress = (SeekBar) findViewById(R.id.sb_progress); imgPlay= (ImageView) findViewById(R.id.iv_play); imgControll = (ImageView) findViewById(R.id.iv_play_controll); tvTime = (TextView) findViewById(R.id.tv_time); //surfaceView绑定生命周期 holder = surfaceView.getHolder(); holder.addCallback(this); //设置默认值 imgPlay.setVisibility(View.VISIBLE); imgControll.setImageResource(android.R.drawable.ic_media_play); } /** * surfaceViewa绑定生命周期需要回调的方法 * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { //播放器绑定surfaceView mediaPlayer.setDisplay(holder); //开启线程 updateThread = new UpdateThread(); updateThread.start(); flag = true; } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { //关闭线程,释放资源 flag = false; if(mediaPlayer != null){ mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer = null; } } @Override public void onClick(View v) { switch (v.getId()){ case R.id.iv_play: imgPlay.setVisibility(View.GONE); imgControll.setImageResource(android.R.drawable.ic_media_pause); mediaPlayer.start(); break; case R.id.iv_play_controll: if(mediaPlayer.isPlaying()){//正在播放--暂停按钮 imgPlay.setVisibility(View.VISIBLE); imgControll.setImageResource(android.R.drawable.ic_media_play); mediaPlayer.pause(); }else{//暂停播放 imgPlay.setVisibility(View.GONE); imgControll.setImageResource(android.R.drawable.ic_media_pause); mediaPlayer.start(); } break; } } @Override protected void onDestroy() { // super.onDestroy(); } }
效果: