转载自

Android MediaPlayer使用方法简单介绍

播放音频

  android中播放音频可以使用MediaPlayer类来实现,一下是它的一些方法:

              方法名             功能描述
            setDataSource()        设置要播放的音频文件的位置。
            prepare()            在开始播放之前调用这个方法完成准备工作。
            start()               开始或继续播放音频。
            pause()               暂停播放音频。
            reset()              将 MediaPlayer 对象重置到刚刚创建的状态。
            seekTo()             从指定的位置开始播放音频。
            stop()                     停止播放音频。调用这个方法后的 MediaPlayer 对象无法再播放音频。
            release()             释放掉与 MediaPlayer 对象相关的资源。
            isPlaying()             判断当前 MediaPlayer 是否正在播放音频。
            getDuration()           获取载入的音频文件的时长。

 在安卓系统中,播放音频最简单的方法是使用内置的媒体播放器(MediaPlayer类)。MediaPlayer既可以播放本地文件,也可以播放来自URL的网络数据流。
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
 
3)对播放器的主要控制方法:
Android通过控制播放器的状态的方式来控制媒体文件的播放,其中:
prepare()和prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
start()是真正启动文件播放的方法,
pause()和stop()比较简单,起到暂停和停止播放的作用,
seekTo()是定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。
release()可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
 
reset()可以使播放器从Error状态中恢复过来,重新会到Idle状态。在重置MediaPlayer的时候使用,重置完,重新setDataResource prepare start,播放下一首
 
4)设置播放器的监听器:
MediaPlayer提供了一些设置不同监听器的方法来更好地对播放器的工作状态进行监听,以期及时处理各种情况,
如: setOnCompletionListener(MediaPlayer.OnCompletionListener listener)、
setOnErrorListener(MediaPlayer.OnErrorListener listener)等,设置播放器时需要考虑到播放器可能出现的情况设置好监听和处理逻辑,以保持播放器的健壮性。

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();
}
}

效果:

MediaPlayer简单使用,绑定surfaceView实现播放视频的功能的更多相关文章

  1. 使用MediaPlayer类和SurfaceView来播放视频

    MediaPlayer可以播放视频,只需需要SurfaceView的配合,SurfaceView主要用于显示MediaPlayer播放的视频流媒体的画面渲染. SurfaceView是配合MediaP ...

  2. 运用surfaceView与MediaPlayer实现播放视频的功能

    该程序运用了surfaceView与MediaPlayer结合,实现播放视频,surfaceView详情请见 SurfaceView的使用 使用了第三方包Volly里面的方法StringQueue下载 ...

  3. android SurfaceView中播放视频 按视频的原始比例播放

    OnPreparedListener mediaPlayerOnPreparedListener = new OnPreparedListener() { @Override public void ...

  4. Android--SurfaceView播放视频

    前言 本篇博客讲解一下如何在Android下,使用SurfaceView播放一个视频流媒体.之前有讲到如何使用MediaPlayer播放音频流媒体,其实MediaPlayer还可以播放视频,只需需要S ...

  5. android 98 MediaPlayer+SurfaceView播放视频

    package com.itheima.videoplayer; import java.io.IOException; import android.media.MediaPlayer; impor ...

  6. WPF播放视频

    在现在的项目中需要使用到播放视频的功能,本来打算使用VLC来做的.后来发现WPF 4.0之后新增了MediaElement类,可以实现视频播放. <Grid> <Grid.RowDe ...

  7. [转]Android WebView播放视频(包括全屏播放),androidwebview

    Android WebView播放视频(包括全屏播放),androidwebview 最近项目开发中用到了WebView播放视频的功能,总结了开发中犯过的错误,这些错误在开发是及容易遇到的,所以我这里 ...

  8. 使用MediaPlayer和SurfaceView播放视频

    使用VideoView播放视频简单.方便,丹有些早期的开发者更喜欢使用MediaPlayer来播放视频,但由于MediaPlayer主要用于播放音频,因此它没有提供图像输出界面,此时 需要借助于Sur ...

  9. Android MediaPlayer和SurfaceView播放视频

    昨天介绍了VideoView播放视频,今天再介绍一种播放视频的方法MediaPlayer和SurfaceView,MediaPlayer播放音频,SurfaceView来显示图像,具体步骤如下: 1. ...

随机推荐

  1. Spring入门(10)-Spring JDBC

    Spring入门(10)-Spring JDBC 0. 目录 JdbcTemplate介绍 JdbcTemplate常见方法 代码示例 参考资料 1. JdbcTemplate介绍 JdbcTempl ...

  2. BestCoder Round #71 (div.2) (hdu 5620 菲波那切数列变形)

    KK's Steel Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  3. 通用FASTREPORT打印模块及接口方法

    untFastReport.dfm文件: object frmFastReport: TfrmFastReport OldCreateOrder = False Height = 405 Width ...

  4. 转载JQuery 中empty, remove 和 detach的区别

    转载 http://www.cnblogs.com/lisongy/p/4109420.html .empty()  描述: 从DOM中移除集合中匹配元素的所有子节点. 这个方法不接受任何参数. 这个 ...

  5. mime type 概要介绍

    内容类型 内容类型(Content-Type),这个头部领域用于指定消息的类型.一般以下面的形式出现. Content-Type: [type]/[subtype]; parameter type t ...

  6. java实现抓取某公司官网新闻

    这里先说一下,实习期的一个项目,当时并没有该合作公司的获取新闻的接口,但是项目又急着上线,所以总监就让我来做一个简单的抓取,现将主要的工具类NewsUtil.java贴出来供大家参考. NewsUti ...

  7. python的深拷贝和浅拷贝

    import copy list1=[1,2,3,4,5] c_list1=list1 c_list1[0]=-1 for i in list1: print str(i)+' ', #输出的世 -1 ...

  8. Oracle DataGuard 物理Standby 搭建(下)

    主备库切换 Switchover 一般SWITCHOVER切换都是计划中的切换,特点是在切换后,不会丢失任何的数据,而且这个过程是可逆的,整个DATA GUARD环境不会被破坏,原来DATA GUAR ...

  9. SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治

    Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://a ...

  10. hdu 5533 Dancing Stars on Me 水题

    Dancing Stars on Me Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.p ...