activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SurfaceView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="300dp" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="00:00/00:00"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="播放"/>
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暂停"/>
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="停止"/>
<Button
android:id="@+id/replay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="重播"/>
</LinearLayout>
</LinearLayout>
MainActivity.class
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
/**SurfaceView内部采用双缓存机制,它会缓存视频中的流数据,将数据进行渲染之后推送到屏幕上做显示。
简单来讲,他就是一个显示视频的屏幕。*/
private SurfaceView sv;
private SurfaceHolder holder;
private SeekBar seekbar;
private MediaPlayer player;
private TextView time;
private Button play;
private Button pause;
private Button stop;
private Button replay;
private int duration;
private boolean isUpdateBar;
// 获取视频路径
String path = Environment.getExternalStorageDirectory() + "/Movies/Uptown Funk.mp4";
// 播放器的几个状态,我们可以通过状态码来判断
public static final int PLAYING = 1; // 播放状态
public static final int PAUSING = 2; // 暂停状态
public static final int STOPPING = 3; // 停止状态
private int CURRENT = 0; // 当前状态
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sv = findViewById(R.id.sv);
seekbar = findViewById(R.id.seekbar);
play = findViewById(R.id.play);
pause = findViewById(R.id.pause);
stop = findViewById(R.id.stop);
replay = findViewById(R.id.replay);
time = findViewById(R.id.time);
play.setOnClickListener(this);
pause.setOnClickListener(this);
stop.setOnClickListener(this);
replay.setOnClickListener(this);
holder = sv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 设置缓冲
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//开始拖动seekbar的时候停止更新seekbar
stopSeekBar();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//停止拖动seekbar的时候定位到相应的位置,并且开始更新seekbar
if(player != null) {
if(CURRENT == PLAYING) {
player.seekTo(seekBar.getProgress());
updateSeekBar();
}
}
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.play:
try {
if (player != null) {
if (CURRENT == PLAYING) { //当前是播放状态
return;
} else if (CURRENT == PAUSING) { // 当前是暂停状态
player.seekTo(seekbar.getProgress());
player.start();
CURRENT = PLAYING;
updateSeekBar();
return;
}
}
if (CURRENT == 0 || CURRENT == STOPPING) { //如果是最开始的状态或者是停止状态
// 创建一个播放器对象
player = new MediaPlayer();
// 设置路径
player.setDataSource(path);
// 准备
player.prepare();
// 获取视频最大的时长(毫秒为单位)
duration = player.getDuration();
// 设置seekBar的最大值
seekbar.setMax(duration);
// 格式化最大时间
String lastTime = formatTime(duration);
time.setText("00:00/" + lastTime);
player.seekTo(seekbar.getProgress());
// 视频开始播放
player.start();
// 更新seekBar
updateSeekBar();
// 设置输出画面
player.setDisplay(holder);
CURRENT = PLAYING;
}
} catch(IOException e){
e.printStackTrace();
}
break;
case R.id.pause: // 暂停
if(player != null && CURRENT == PLAYING) {
player.pause();
stopSeekBar();
CURRENT = PAUSING;
}
break;
case R.id.stop: // 停止播放
if(player != null) {
if(CURRENT == PLAYING || CURRENT == PAUSING) {
stopSeekBar();
seekbar.setProgress(0);
time.setText("00:00/"+formatTime(duration));
player.stop(); // 播放器处于停止状态 所有设置都清零
player.release(); // 释放资源
CURRENT = STOPPING;
}
}
break;
case R.id.replay: // 重播
if(player != null) {
try{
player.reset(); // 播放器空闲状态 要想播放必须重新设置路径还要进入准备状态
player.setDataSource(path);
player.prepare(); // 准备状态
player.start();
CURRENT = PLAYING;
}catch (IOException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
//更新进度条
private void updateSeekBar(){
isUpdateBar = true;
new Thread(new Runnable() {
@Override
public void run() {
while(isUpdateBar) {
// 每秒更新一次
SystemClock.sleep(1000);
if(player != null && CURRENT == PLAYING){
seekbar.setProgress(player.getCurrentPosition());
// 在主线程中更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
String current = formatTime(player.getCurrentPosition()); // 播放进度
String durationString = formatTime(duration); // 最大时间
time.setText(current + "/" + durationString);
}
});
}
}
}
}).start();
}
private String formatTime(int duration) {
int second = duration / 1000; // 先转换成总秒数 270s
int minute = second / 60; // 在转换成总分钟 4
second = second - minute * 60; // 转换成秒位置上的秒数 30s
StringBuilder sb = new StringBuilder();
sb.append(minute > 10 ? minute + "" : "0" + minute); // 04
sb.append(":");
sb.append(second > 10 ? second + "" : "0" + second);// 04:30
return sb.toString();
}
private void stopSeekBar(){
isUpdateBar = false;
}
}
媒体控制器
MainActivity.class
public class MainActivity extends AppCompatActivity {
/**videoView播放器*/
private VideoView mVideoView;
/**媒体控制器*/
private MediaController mController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置窗口格式为半透明
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.activity_main);
// 绑定videoView控件
mVideoView = findViewById(R.id.video_view);
// 创建MediaController对象
mController = new MediaController(this);
// 准备播放文件
File video = new File(Environment.getExternalStorageDirectory()+"/Movies/小城大事-张学友.mp4");
// 如果文件存在
if(video.exists()) {
mVideoView.setVideoPath(video.getPath());
// 设置VideoView与Controller建立关联
mVideoView.setMediaController(mController);
// 设置controller和videoView建立关联
mController.setMediaPlayer(mVideoView);
//让VideoView获取焦点
mVideoView.requestFocus();
}
}
}