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. ...
随机推荐
- Spring入门(10)-Spring JDBC
Spring入门(10)-Spring JDBC 0. 目录 JdbcTemplate介绍 JdbcTemplate常见方法 代码示例 参考资料 1. JdbcTemplate介绍 JdbcTempl ...
- 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 ...
- 通用FASTREPORT打印模块及接口方法
untFastReport.dfm文件: object frmFastReport: TfrmFastReport OldCreateOrder = False Height = 405 Width ...
- 转载JQuery 中empty, remove 和 detach的区别
转载 http://www.cnblogs.com/lisongy/p/4109420.html .empty() 描述: 从DOM中移除集合中匹配元素的所有子节点. 这个方法不接受任何参数. 这个 ...
- mime type 概要介绍
内容类型 内容类型(Content-Type),这个头部领域用于指定消息的类型.一般以下面的形式出现. Content-Type: [type]/[subtype]; parameter type t ...
- java实现抓取某公司官网新闻
这里先说一下,实习期的一个项目,当时并没有该合作公司的获取新闻的接口,但是项目又急着上线,所以总监就让我来做一个简单的抓取,现将主要的工具类NewsUtil.java贴出来供大家参考. NewsUti ...
- python的深拷贝和浅拷贝
import copy list1=[1,2,3,4,5] c_list1=list1 c_list1[0]=-1 for i in list1: print str(i)+' ', #输出的世 -1 ...
- Oracle DataGuard 物理Standby 搭建(下)
主备库切换 Switchover 一般SWITCHOVER切换都是计划中的切换,特点是在切换后,不会丢失任何的数据,而且这个过程是可逆的,整个DATA GUARD环境不会被破坏,原来DATA GUAR ...
- SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治
Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://a ...
- 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 ...