转载自

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. Web Service学习之五:WSDL详解

    WSDL是Web Service定义文档,不同平台 不同语言实现Web Service遵循的共同协议 ,在解析XML时按照各自语言的特点解析成相应的具体类.方法.参数和数据类型. WSDL是一个XML ...

  2. struts2+Hibernate4+spring3+EasyUI环境搭建之三:引入sututs2以及spring与sututs2整合

    1.引入struts2 <!-- struts2 和心包 排除javassist 因为hibernate也有 会发生冲突--> <dependency> <groupId ...

  3. [转载]Linux LVM硬盘管理及LVM扩容

    最近项目中一直在用Linux,其中涉及到了Linux的LVM,本来想自己写一篇关于LVM的文章,搜了一下,发现了一篇更好的,转载过来,也感谢作者gaojun 原文Linux LVM硬盘管理及LVM扩容 ...

  4. MongoDB的update有关问题(JAVA)——如何一次更新所有的相同记录

    MongoDB的update问题(JAVA)——怎么一次更新所有的相同记录用如下这个函数:public WriteResult update(DBObject q,  DBObject o,  boo ...

  5. CSS 酷站

    http://mikkelbang.com/#!videos

  6. POJ 3672 Long Distance Racing (模拟)

    题意:给定一串字符,u表示是上坡,d表示下坡,f表示平坦的,每个有不同的花费时间,问你从开始走,最远能走到. 析:直接模拟就好了,没什么可说的,就是记下时间时要记双倍的,因为要返回来的. 代码如下: ...

  7. C#中托管与非托管

    在.net 编程环境中,系统的资源分为托管资源和非托管资源. 对于托管的资源的回收工作,是不需要人工干预回收的,而且你也无法干预他们的回收,所能够做的 只是了解.net CLR如何做这些操作.也就是说 ...

  8. WinDbg x 64 使用 SOS: 无法找到运行时 DLL (clr.dll)

     http://www.datazx.cn/Forums/en-US/59aa78c9-dc05-43c8-9efe-e7b132056afc/action?threadDisplayName=win ...

  9. OpenStack API 与 CloudStack API 模块比较

    OpenStack API Block Storage Service API Compute API Compute API extensions Identity Service API and ...

  10. IE 、Firefox、Chrome 浏览器在 F12 控制台下切换至不同框架介绍

    有不少网页的页面,还在使用 iframe 标签,而此时,相当于页面有两个 window 对象,一个为当前页面 window ,另一个则为 iframe 页面下的 window .因为,有时候需要在 c ...