MediaPlayer简单使用,绑定surfaceView实现播放视频的功能
转载自
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());
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实现播放视频的功能的更多相关文章
- 使用MediaPlayer类和SurfaceView来播放视频
MediaPlayer可以播放视频,只需需要SurfaceView的配合,SurfaceView主要用于显示MediaPlayer播放的视频流媒体的画面渲染. SurfaceView是配合MediaP ...
- 运用surfaceView与MediaPlayer实现播放视频的功能
该程序运用了surfaceView与MediaPlayer结合,实现播放视频,surfaceView详情请见 SurfaceView的使用 使用了第三方包Volly里面的方法StringQueue下载 ...
- android SurfaceView中播放视频 按视频的原始比例播放
OnPreparedListener mediaPlayerOnPreparedListener = new OnPreparedListener() { @Override public void ...
- Android--SurfaceView播放视频
前言 本篇博客讲解一下如何在Android下,使用SurfaceView播放一个视频流媒体.之前有讲到如何使用MediaPlayer播放音频流媒体,其实MediaPlayer还可以播放视频,只需需要S ...
- android 98 MediaPlayer+SurfaceView播放视频
package com.itheima.videoplayer; import java.io.IOException; import android.media.MediaPlayer; impor ...
- WPF播放视频
在现在的项目中需要使用到播放视频的功能,本来打算使用VLC来做的.后来发现WPF 4.0之后新增了MediaElement类,可以实现视频播放. <Grid> <Grid.RowDe ...
- [转]Android WebView播放视频(包括全屏播放),androidwebview
Android WebView播放视频(包括全屏播放),androidwebview 最近项目开发中用到了WebView播放视频的功能,总结了开发中犯过的错误,这些错误在开发是及容易遇到的,所以我这里 ...
- 使用MediaPlayer和SurfaceView播放视频
使用VideoView播放视频简单.方便,丹有些早期的开发者更喜欢使用MediaPlayer来播放视频,但由于MediaPlayer主要用于播放音频,因此它没有提供图像输出界面,此时 需要借助于Sur ...
- Android MediaPlayer和SurfaceView播放视频
昨天介绍了VideoView播放视频,今天再介绍一种播放视频的方法MediaPlayer和SurfaceView,MediaPlayer播放音频,SurfaceView来显示图像,具体步骤如下: 1. ...
随机推荐
- Linux下搭建jdk
1.上oracle下载jdk-8u73-linux-x64.gz文件(其他版本的也可以,不过本教程以.gz格式为准,其他格式没有尝试过,不造怎么弄) 2.在linux桌面上右键->打开终端 3. ...
- 个人思考:能否sub.prototye=sup.prototype实现继承
var Sup=function(name){ this.name=name; }; var Sub=function(name){ this.name=name; }; Sup.prototype. ...
- 第二百八十六天 how can I 坚持
bug不断啊,头疼. 今天早上到的倒是挺早. 中午吃的黄焖鸡,晚上加了会班. 勇江的鱼都死了,杨建的还剩3条,晚上到家都快十点了,还洗了衣服,没捞出来呢, 希望可以请下来假吧. 晾上衣服睡觉.
- ocp 1Z0-051 141-175题解析
141. View the Exhibitand examine the structure of CUSTOMERS and GRADES tables. You need to displayna ...
- 转载C#中堆(heap)和栈(stack)的区别
转载原地址 http://www.cnblogs.com/wangshenhe/archive/2013/02/18/2916275.html [转]C#堆和栈的区别 理解堆与栈对于理解.NET中的 ...
- Java常用类(String、StringBuffer、Math、Arrays)
1.String 操作对象时会重新分配堆内存,栈内存的引用会重新指向新的堆内存 2.StringBuffer(字符串缓存区) 操作的对象一直都是一个 3.Math Math.max(xx,xx); M ...
- Starter Set of Functional Interfaces
Java Development Kit 8 has a number of functional interfaces. Here we review the starter set-the int ...
- 十六进制转十进制 - C
我们经常碰到16进制数转10进制的情况,使用下面的C程序即可完成上述工作. 那么他是怎样的工作原理呢? 6.2.5 十六进制数转换成十进制数 16进制就是逢16进1,但我们只有0~9这十个数字,所以我 ...
- Vieta定理
一元$n$次方程$$P(x)=a_{n}x^{n}+a_{n-1}x^{n-1}+\cdots+a_{a}x+a_{0}=a_{n}(x-x_{1})(x-x_{2})\cdots (x-x_{n}) ...
- Meta键盘
由于著名的编辑器Emacs中用到Meta键,但如今大多国人所用键盘上实际并无此键,想必多有不明之处,故多方收集资料撰写此文,简要描述了Meta键及相关键盘的发展始末,至于在Emacs上如何使用国人键盘 ...