第5天使用MediaPlayer和SurfaceView高级应用-播放视频-正弦波
效果图
代码
while (true){
Canvas canvas = surfaceHolder.lockCanvas();
if(canvas==null){//如果画布为空,直接结束线程
break;}
int y=(int)(100* Math.sin(x*Math.PI/180)+400);
canvas.drawPoint(x++,y,paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
Android绘制函数图象及正弦函数的介绍
https://www.jianshu.com/p/ae4e69437efb
一.为什么使用surfaceview播放视频:
在Android中,一般播放音频时我们可以去使用Android提供的MediaPlayer类,但是想要播放视频仅仅依靠MediaPlayer类是远远不够的...这里还需要使用到一个SurfaceView这个组件来完成..为什么?因为像视频和SD图形等都需要迅速的更新...如果这个更新实在主线程内去完成,那么显然是不合理的,因为一个视频的播放,系统会首先确定视频的格式,然后得到视频的编码..然后对编码进行解码,得到一帧一帧的图像,最后在画布上进行迅速更新...这就是视频播放的机制...那么这个过程显然我们需要在另外一个线程内部去完成...这样主线程的其他内容,比如说其他的渲染操作,图片加载什么的,就不会导致主线程阻塞...这样我们就可以使用SurfaceView来完成
二.MediaPlayer使用到的方法:
- 调用player.setDataSource()方法设置要播放的资源,可以是文件、文件路径、或者URL。
- 调用MediaPlayer.setDisplay(holder)设置surfaceHolder,surfaceHolder可以通过surfaceview的getHolder()方法获得。
- 调用MediaPlayer.prepare()来准备。
- 调用MediaPlayer.start()来播放视频。
三.画板代码:
public class HuaBan extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Canvas canvas;
private Paint paint;
private Path path=new Path();//路径
private Thread thread=new Thread(new Runnable() {
@Override
public void run() {
while(true){
paint=new Paint();
paint.setStyle(Paint.Style.STROKE);//设置不是填充
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10f);
canvas=holder.lockCanvas();//锁定画布
if(canvas==null){//如果画布为空,直接结束线程
break;}
//按照路径画图
canvas.drawPath(path,paint);
holder.unlockCanvasAndPost(canvas);//解除画布
}
}
});
//重写触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();//获得事件类型
switch (action){
case MotionEvent.ACTION_DOWN://按下
path.moveTo(event.getX(),event.getY());
break;
case MotionEvent.ACTION_MOVE://移动
path.lineTo(event.getX(),event.getY());
break;
case MotionEvent.ACTION_UP://移动
break;
}
return true;
}
public HuaBan(Context context) {
super(context);
}
public HuaBan(Context context, AttributeSet attrs) {
super(context, attrs);
holder=getHolder();
holder.addCallback(this);
}
public HuaBan(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public HuaBan(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}
四.视频代码:
(1)布局:
<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"
tools:context=".video.VedioActivity"
android:orientation="vertical">
<!--不需要自定义SurfaceView,不需要我们在上面画画,我们只需要将视频放到surfaceView中播放-->
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="match_parent"
android:layout_height="300dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp">
<Button
android:id="@+id/play"
android:text="播放"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:text="暂停"
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
(2)Java代码:
public class VedioActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private SurfaceView surfaceView;
private Button play,pause;
private MediaPlayer mediaPlayer;//播放视频
private SurfaceHolder surfaceHolder;//将视频放到持有者上面
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vedio);
initView();
initPlayer();
}
private void initPlayer(){
if(mediaPlayer==null){
mediaPlayer=new MediaPlayer();//创建对象
}
File file = Environment.getExternalStorageDirectory();//获得SD卡根路
File file1 = new File(file, "万能1.mp4");//获得视频的路径
try {
mediaPlayer.setDataSource(file1.getAbsolutePath());//设置视频的路径 可以是SD卡文件的路径 网络视频Url
mediaPlayer.prepare();//准备播本地视频
//mediaPlayer.prepareAsync();//播放网络视频
mediaPlayer.start();//播放视频
} catch (IOException e) {
e.printStackTrace();
}
}
private void initView() {
surfaceView=findViewById(R.id.surfaceview);
pause=findViewById(R.id.pause);
play=findViewById(R.id.play);
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
}
});
play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(!mediaPlayer.isPlaying()){//处于暂停
mediaPlayer.start();
}
}
});
surfaceHolder=surfaceView.getHolder();//获得持有者
surfaceHolder.addCallback(this);//接口回调,获得生命周期
}
//创建生命周期:播放视频
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mediaPlayer.setDisplay(surfaceHolder);//将视频放surfaceholder
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
}