Android之视频播放使用MediaPlayer+SurfaceView代替ViedoView控件

xiaoxiao2021-02-28  100

前言:虽然ViedoView控件可以播放视频,但播放的位置和大小并不受我们的控制,为了对视频有更好的控制权,可以使用MediaPlayer配合SurfaceView来播放视频。

实现效果:

 

转存失败重新上传取消 转存失败重新上传取消

 

 

 

 

1、SurfaceView与MediaPlayer配合使用:

 

[html]  view plain  copy   mediaPlayer.setDisplay(surfaceview.getHolder());//这一步是关键,制定用于显示视频的SurfaceView对象(通过setDisplay())  

 

 

 

2、维护SurfaceView:

通过sufaceView.Callback接口实现,需要实现其三个方法:

 

void surfaceDestroyed(SurfaceHolder holder):当SurfaceHolder被销毁的时候回调。void surfaceCreated(SurfaceHolder holder):当SurfaceHolder被创建的时候回调。void surfaceChange(SurfaceHolder holder):当SurfaceHolder的尺寸发生变化的时候被回调。

 

3、通过MediaPlayer类的Play()与Pause()方法实现视频的暂停与播放。

4、对进度条的布局优化:

在drawable下定义两个xml文件,具体见以下源码。

 

完整源码展示:

MainActivity.Java:

 

[java]  view plain  copy   import android.app.Activity;  import android.content.res.AssetFileDescriptor;  import android.media.AudioManager;  import android.media.MediaPlayer;  import android.media.MediaPlayer.OnPreparedListener;  import android.os.Bundle;  import android.view.SurfaceHolder;  import android.view.SurfaceView;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.ImageButton;  import android.widget.SeekBar;    public class MainActivity extends Activity implements OnClickListener {        private SurfaceView surfaceview;      private MediaPlayer mediaPlayer;      private ImageButton start;      private ImageButton share;      private ImageButton back;      private ImageButton pause;      private SeekBar seekBar;      private boolean isPlaying;      private int currentPosition = 0;        private int postion = 0;            @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);          findViewById();          initView();      }        protected void findViewById() {          // TODO Auto-generated method stub          surfaceview = (SurfaceView) findViewById(R.id.surfaceView);          start = (ImageButton) findViewById(R.id.video_start);          back = (ImageButton) findViewById(R.id.video_back);          pause = (ImageButton) findViewById(R.id.video_pause);          share = (ImageButton) findViewById(R.id.video_share);          seekBar = (SeekBar) findViewById(R.id.seekBar);            }        protected void initView() {          // TODO Auto-generated method stub          mediaPlayer = new MediaPlayer();          surfaceview.getHolder().setKeepScreenOn(true);          surfaceview.getHolder().addCallback(new SurfaceViewLis());          start.setOnClickListener(this);          back.setOnClickListener(this);          pause.setOnClickListener(this);          share.setOnClickListener(this);          seekBar.setOnClickListener(this);      }        private class SurfaceViewLis implements SurfaceHolder.Callback {            @Override          public void surfaceChanged(SurfaceHolder holder, int format, int width,                  int height) {            }            @Override          public void surfaceCreated(SurfaceHolder holder) {              if (currentPosition > 0) {                  // 创建SurfaceHolder的时候,如果存在上次播放的位置,则按照上次播放位置进行播放                  video_play(currentPosition);                  currentPosition = 0;              }          }            @Override          public void surfaceDestroyed(SurfaceHolder holder) {              // 销毁SurfaceHolder的时候记录当前的播放位置并停止播放              if (mediaPlayer != null && mediaPlayer.isPlaying()) {                  currentPosition = mediaPlayer.getCurrentPosition();                  mediaPlayer.stop();              }            }        }        @Override      public void onClick(View v) {          switch (v.getId()) {              case R.id.video_start:                  video_play(0);                  break;              case R.id.video_pause:                  pause();                  break;                  default:                  break;          }      }          /**      * 开始播放      *      * @param msec 播放初始位置      */      protected void video_play(final int msec) {  //      // 获取视频文件地址          try {              mediaPlayer = new MediaPlayer();              //设置音频流类型              mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);              // 设置播放的视频源              AssetFileDescriptor fd = this.getAssets().openFd("Perspective.mp4");              mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),                      fd.getLength());              // 设置显示视频的SurfaceHolder              mediaPlayer.setDisplay(surfaceview.getHolder());//这一步是关键,制定用于显示视频的SurfaceView对象(通过setDisplay())                mediaPlayer.prepareAsync();              mediaPlayer.setOnPreparedListener(new OnPreparedListener() {                    @Override                  public void onPrepared(MediaPlayer mp) {                      mediaPlayer.start();                        // 按照初始位置播放                      mediaPlayer.seekTo(msec);                      // 设置进度条的最大进度为视频流的最大播放时长                      seekBar.setMax(mediaPlayer.getDuration());                      // 开始线程,更新进度条的刻度                      new Thread() {                            @Override                          public void run() {                              try {                                  isPlaying = true;                                  while (isPlaying) {                                      int current = mediaPlayer                                              .getCurrentPosition();                                      seekBar.setProgress(current);                                        sleep(500);                                  }                              } catch (Exception e) {                                  e.printStackTrace();                              }                          }                      }.start();                        start.setEnabled(false);                  }              });              mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {                    @Override                  public void onCompletion(MediaPlayer mp) {                      // 在播放完毕被回调                      start.setEnabled(true);                  }              });                mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {                    @Override                  public boolean onError(MediaPlayer mp, int what, int extra) {                      // 发生错误重新播放                      video_play(0);                      isPlaying = false;                      return false;                  }              });          } catch (Exception e) {              e.printStackTrace();          }        }          /**      * 暂停或继续      */      protected void pause() {          if (mediaPlayer != null && mediaPlayer.isPlaying()) {              mediaPlayer.pause();          }        }          }  

activity_main.xml:

 

 

[html]  view plain  copy   <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" >        <FrameLayout          android:layout_width="match_parent"          android:layout_height="220dp">            <SurfaceView              android:id="@+id/surfaceView"              android:layout_width="match_parent"              android:layout_height="220dp"/>            <LinearLayout              android:layout_width="match_parent"              android:layout_height="30dp"              android:layout_gravity="top"              android:orientation="horizontal"              android:background="@drawable/video_top">                <!--android:alpha="0.3"-->                <ImageButton                  android:id="@+id/video_back"                  android:layout_width="15dp"                  android:layout_height="18dp"                  android:background="@drawable/video_back"                  android:layout_gravity="center"                  android:layout_marginLeft="20dp"></ImageButton>                <ImageButton                  android:id="@+id/video_share"                  android:layout_width="25dp"                  android:layout_height="15dp"                  android:background="@drawable/video_share"                  android:layout_gravity="center"                  android:layout_marginLeft="280dp"                    />            </LinearLayout>                    <LinearLayout              android:layout_width="match_parent"              android:layout_height="30dp"              android:layout_gravity="bottom"              android:orientation="horizontal"              android:background="@drawable/video_bottom">            <ImageButton              android:id="@+id/video_start"              android:layout_width="18dp"              android:layout_height="wrap_content"              android:background="@drawable/video_start"              android:layout_gravity="center"              android:layout_marginLeft="20dp">            </ImageButton>                          <SeekBar                  android:id="@+id/seekBar"                  android:layout_width="250dp"                  android:layout_height="wrap_content"                  android:layout_gravity="center"                  android:layout_marginLeft="20dp"                  android:progressDrawable="@drawable/seekbar_style"                  android:thumb="@drawable/seekbar_thumb"                  android:maxHeight="8dp"                  android:minHeight="8dp"                    />            <ImageButton              android:id="@+id/video_pause"              android:layout_width="15dp"              android:layout_height="18dp"              android:background="@drawable/video_pause"              android:layout_gravity="center"              android:layout_marginLeft="20dp"              />          </LinearLayout>          </FrameLayout>      </RelativeLayout>  

 

 

 

 

 

对进度条的布局优化:

 

[html]  view plain  copy   <?xml version="1.0" encoding="utf-8"?>  <layer-list      xmlns:android="http://schemas.android.com/apk/res/android">      <item >          <shape>              <solid android:color="#c6c6c6" />          </shape>      </item>      <item>          <clip>              <shape>                  <solid android:color="#06a7fa" />              </shape>          </clip>      </item>  </layer-list>  

对进度点的布局优化:

 

 

[html]  view plain  copy   <?xml version="1.0" encoding="UTF-8"?>  <selector xmlns:android="http://schemas.android.com/apk/res/android">      <!-- 按下状态 -->      <item          android:state_pressed="true"          android:drawable="@drawable/video_seekbar_after" />        <!-- 普通无焦点状态 -->      <item          android:state_focused="false"          android:state_pressed="false"          android:drawable="@drawable/video_seekbar_before" />    </selector>   

 

转载请注明原文地址: https://www.6miu.com/read-57395.html

最新回复(0)