一个简单的视频控制播放,使用原生控件进行视频处理,可以根据需要可以自行扩展。
效果图:
遇到的问题1:mediaPlay.setOnPreparedListener()第一次播放无法初始化问题 这个方法不知道什么情况,第二次之后就正常了。使用了异步的方法进行UI数据更新,也是不行。所以另找了方法去实现时间和seekbar拖动控制播放的功能。如果不需要控制,只是显示,就无所谓了、
解决方法:
使用mediaPlay.setOnPreparedListener()代替,内部调用setOnBufferingUpdateListener()方法进行数据更新,然后搞个线程将UI更新一下就ok了,效果还行。
代码片段(因为写demo喜欢写一起,有点乱,就先只放代码片段,需要完整的私聊发邮箱地址):
private SurfaceView surfaceview;
private MediaPlayer player;
SurfaceHolder holder;
private SeekBar video_seekbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
video_seekbar = (SeekBar) findViewById(R.id.video_seekbar);
surfaceview = (SurfaceView) findViewById(R.id.surfaceview);
video_time = (TextView) findViewById(R.id.video_time);
holder = surfaceview.getHolder();
player = new MediaPlayer();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
//开始运行时,就直接播放
Play();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//当画面发生变化执行
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//当画面不见得时候执行
stop();
}
});
video_seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = seekBar.getProgress();
//在当前位置播放
player.seekTo(progress);
}
});
}
private void Play() {
//一定要先重置!!!
player.reset();
//播放模式
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
//放视频
Uri uri = Uri.parse("https://sy.hyylm.com/ff0c98f290ed496597e392c2befacae1.mp4");
player.setDataSource(MainActivity.this, uri);
//把视频放到surfaceview上
player.setDisplay(holder);
//准备工作
player.prepare();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
Log.e("test_mediaPlayer", mediaPlayer.getCurrentPosition() + "");
// video_seekbar.setProgress(mediaPlayer.getCurrentPosition());
video_seekbar.setMax(mediaPlayer.getDuration());
new Thread(new Runnable() {
@Override
public void run() {
while (video_seekbar.getProgress() <= video_seekbar.getMax()) {
int currentPosition = 0;
try {
try {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
currentPosition = mediaPlayer.getCurrentPosition();
video_seekbar.setProgress(currentPosition);
int duration2 = mediaPlayer.getDuration();//获取音乐总时长
int position = mediaPlayer.getCurrentPosition();//获取当前播放的位置
// handler.sendEmptyMessage(0);
Message msg = Message.obtain();
msg.what = 0;
//创建Bundle
Bundle bundle = new Bundle();
bundle.putString("key", calculateTime(position / 1000) + " / " + calculateTime(duration2 / 1000));
//为Message设置Bundle数据
msg.setData(bundle);
//发送消息
handler.sendMessage(msg);
}
}
} catch (IllegalStateException e) {
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
});
}
});
//开始了
player.start();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 停止视频播放的方法
*/
public void stop() {
try {
if (player != null) {
player.pause();
player.stop();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// canProgress = false;
if (player != null) {
player.release();
player = null;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
stop();
}
//计算播放时间
public String calculateTime(int time) {
int minute;
int second;
if (time >= 60) {
minute = time / 60;
second = time % 60;
//分钟在0~9
if (minute < 10) {
//判断秒
if (second < 10) {
return "0" + minute + ":" + "0" + second;
} else {
return "0" + minute + ":" + second;
}
} else {
//分钟大于10再判断秒
if (second < 10) {
return minute + ":" + "0" + second;
} else {
return minute + ":" + second;
}
}
} else {
second = time;
if (second >= 0 && second < 10) {
return "00:" + "0" + second;
} else {
return "00:" + second;
}
}
}
布局文件也比较简单:
<RelativeLayout 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:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<uk.co.senab.photoview.PhotoView
android:id="@+id/image_sf"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"
android:visibility="gone"/>
<com.youth.banner.Banner
android:id="@+id/testBanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="250dp"
android:visibility="visible">
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="8" />
</RelativeLayout>
<SeekBar
android:id="@+id/video_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:max="100"
android:maxHeight="1.0dip"
android:minHeight="1.0dip"
android:progress="0" />
<TextView
android:id="@+id/video_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="播放时间"
android:paddingTop="40dp"/>
</RelativeLayout>
代码那里贴的部分代码,只要代码片段就是监听部分,其他的就没什么了。最大的优点应该就是因为是用系统原始控件搞得,不至于像第三方那么大,宽展难受。如果是对视频播放要求比较高的,建议使用第三方的去弄,毕竟方便。