简介
Android 入门视频播放器一般采用封装好的VideoView或MediaPlayer+SurfaceView两种类型,其中VideoView高度封装并不适合深入了解其中原理,下面利用SurfaceView+MediaPlay实现一个简单的视频播放器,视频播放器的效果如下所示:
效果图
项目代码
package com.example.mediaplayer_1;
import androidx.appcompat.app.AppCompatActivity;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Button;
import android.view.View;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
//定义控件与状态量
private TextView tv_star, tv_end; //视频起始点、终点显示
private SeekBar seekBar;
private Button play, pause, stop, replay;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private MediaPlayer mediaPlayer;
private boolean noPlay=true; //定义播放状态
private Uri uri; //播放链接 本地资源库
private boolean isSeekbarChaning;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
//控件绑定与设置
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
,WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏显示
play = findViewById( R.id.button ); //绑定控件
pause = findViewById( R.id.button2 );
stop = findViewById( R.id.button3 );
replay = findViewById( R.id.button4 );
tv_star = findViewById( R.id.textView );
tv_end = findViewById( R.id.textView2 );
seekBar = findViewById( R.id.seekBar );
surfaceView = findViewById( R.id.surfaceView );
surfaceHolder = surfaceView.getHolder(); //surfaceHolder是surface监听器,感知创建,销毁,改变
mediaPlayer = new MediaPlayer(); //创建MediaPlayer对象
uri = Uri.parse( "android.resource://com.example.mediaplayer_1/" + R.raw.video ); //获取本地视频资源【模块名+资源名】
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build();
mediaPlayer.setAudioAttributes( audioAttributes ); //设置多媒体类型
mediaPlayer.setLooping( false );
//控件功能设计
//1.播放
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { //监听器分开写,被按下&初始状态为true,则播放
if(noPlay){
play();
setSeekto(0);
noPlay=false; //播放状态功能改为false
}else{
mediaPlayer.start();//继续播放视频
}
}
});
//2.暂停
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mediaPlayer.isPlaying()){ //正在播放状态则暂停
mediaPlayer.pause();
}
}
});
//3.停止
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
noPlay=true;//更改视频状态为未播放状态
}
}
});
replay.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mediaPlayer != null && mediaPlayer.isPlaying()){
mediaPlayer.seekTo( 0 );
noPlay = false;
}
}
} );
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Toast.makeText(MainActivity.this, "视频播放完毕", Toast.LENGTH_SHORT).show();
}
});
//进度条
seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) { //拖动进度条进度改变时调用
int time_end = mediaPlayer.getDuration() / 1000 ; //获取视频时长
tv_end.setText(calaculateTime( time_end ));
int time_now = mediaPlayer.getCurrentPosition() / 1000;
tv_star.setText( calaculateTime( time_now ) );
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) { //拖动进度条开始拖动的时候调用
setSeekbarChaning(true);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) { //拖动进度条停止拖动的时候调用
setSeekbarChaning( false );
setSeekto( seekBar.getProgress() ); //进度条跳转至拉伸位置,视频跳转
tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));
}
} );
}
public void play() {
mediaPlayer.reset();//重置MediaPlayer
mediaPlayer.setDisplay( surfaceHolder );//把视频画面输出至SurfaceView中
try {
mediaPlayer.setDataSource( getApplicationContext(), uri ); //读取资源库指定文件
mediaPlayer.prepare();//预加载
} catch (Exception e) {
e.printStackTrace(); //捕获异常
}
mediaPlayer.start();
int duration = mediaPlayer.getDuration(); //获取视频总时间
seekBar.setMax( duration ); //将音乐总时间设置为Seekbar的最大值
Timer timer = new Timer();
timer.schedule( new TimerTask() {
@Override
public void run() {
if (!isSeekbarChaning) { //判断seekbar是否修改完毕
if (!noPlay) { //判断视频是否暂停
seekBar.setProgress( mediaPlayer.getCurrentPosition() );
}
}
}
}, 0, 50 );
}
//时间换算
public String calaculateTime(int time){
int minute, second;
if(time > 60){
minute = time / 60; //分钟取整
second = time % 60; //秒钟取余
//分钟再0~9
if(minute >= 0 && minute < 10){ //0x:0x
//判断秒
if(second >= 0 && second < 10){
return "0"+minute+":"+"0"+second;
}else {
return "0"+minute+":"+second;
}
}else {
//分钟大于10再判断秒
if(second >= 0 && second < 10){
return minute+":"+"0"+second;
}else {
return minute+":"+second;
}
}
}else if(time < 60){
second = time;
if(second >= 0 && second < 10){
return "00:"+"0"+second;
}else {
return "00:"+ second;
}
}
return null;
}
//改变进度条 bool状态
public void setSeekbarChaning(boolean isSeekbar){
isSeekbarChaning = isSeekbar;
}
public void setSeekto(int progress){
mediaPlayer.seekTo( progress );
}
public String formattime(long time){
String min= (time/(1000*60))+"";
String second= (time%(1000*60)/1000)+"";
if(min.length()<2){
min = 0 + min;
}
if(second.length()<2){
second = 0 + second;
}
return min +":"+ second;
}
@Override
protected void onDestroy() {
if(mediaPlayer!=null){
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
mediaPlayer.release();
}
super.onDestroy(); //释放资源
}
}
布局比较简单,就不上传了,完整代码链接:https://download.youkuaiyun.com/download/Harrison509/12742083