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

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

实现效果:

 

uploading.4e448015.gif转存失败重新上传取消
uploading.4e448015.gif转存失败重新上传取消

 

 

 

 

1、SurfaceView与MediaPlayer配合使用:

 

[html]  view plain  copy
 
  1. 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
 
  1. import android.app.Activity;  
  2. import android.content.res.AssetFileDescriptor;  
  3. import android.media.AudioManager;  
  4. import android.media.MediaPlayer;  
  5. import android.media.MediaPlayer.OnPreparedListener;  
  6. import android.os.Bundle;  
  7. import android.view.SurfaceHolder;  
  8. import android.view.SurfaceView;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.ImageButton;  
  12. import android.widget.SeekBar;  
  13.   
  14. public class MainActivity extends Activity implements OnClickListener {  
  15.   
  16.     private SurfaceView surfaceview;  
  17.     private MediaPlayer mediaPlayer;  
  18.     private ImageButton start;  
  19.     private ImageButton share;  
  20.     private ImageButton back;  
  21.     private ImageButton pause;  
  22.     private SeekBar seekBar;  
  23.     private boolean isPlaying;  
  24.     private int currentPosition = 0;  
  25.   
  26.     private int postion = 0;  
  27.   
  28.   
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.         findViewById();  
  35.         initView();  
  36.     }  
  37.   
  38.     protected void findViewById() {  
  39.         // TODO Auto-generated method stub  
  40.         surfaceview = (SurfaceView) findViewById(R.id.surfaceView);  
  41.         start = (ImageButton) findViewById(R.id.video_start);  
  42.         back = (ImageButton) findViewById(R.id.video_back);  
  43.         pause = (ImageButton) findViewById(R.id.video_pause);  
  44.         share = (ImageButton) findViewById(R.id.video_share);  
  45.         seekBar = (SeekBar) findViewById(R.id.seekBar);  
  46.   
  47.   
  48.   
  49.     }  
  50.   
  51.     protected void initView() {  
  52.         // TODO Auto-generated method stub  
  53.         mediaPlayer = new MediaPlayer();  
  54.         surfaceview.getHolder().setKeepScreenOn(true);  
  55.         surfaceview.getHolder().addCallback(new SurfaceViewLis());  
  56.         start.setOnClickListener(this);  
  57.         back.setOnClickListener(this);  
  58.         pause.setOnClickListener(this);  
  59.         share.setOnClickListener(this);  
  60.         seekBar.setOnClickListener(this);  
  61.     }  
  62.   
  63.     private class SurfaceViewLis implements SurfaceHolder.Callback {  
  64.   
  65.         @Override  
  66.         public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  67.                 int height) {  
  68.   
  69.         }  
  70.   
  71.         @Override  
  72.         public void surfaceCreated(SurfaceHolder holder) {  
  73.             if (currentPosition > 0) {  
  74.                 // 创建SurfaceHolder的时候,如果存在上次播放的位置,则按照上次播放位置进行播放  
  75.                 video_play(currentPosition);  
  76.                 currentPosition = 0;  
  77.             }  
  78.         }  
  79.   
  80.         @Override  
  81.         public void surfaceDestroyed(SurfaceHolder holder) {  
  82.             // 销毁SurfaceHolder的时候记录当前的播放位置并停止播放  
  83.             if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  84.                 currentPosition = mediaPlayer.getCurrentPosition();  
  85.                 mediaPlayer.stop();  
  86.             }  
  87.   
  88.         }  
  89.   
  90.     }  
  91.   
  92.     @Override  
  93.     public void onClick(View v) {  
  94.         switch (v.getId()) {  
  95.             case R.id.video_start:  
  96.                 video_play(0);  
  97.                 break;  
  98.             case R.id.video_pause:  
  99.                 pause();  
  100.                 break;  
  101.   
  102.   
  103.             default:  
  104.                 break;  
  105.         }  
  106.     }  
  107.   
  108.   
  109.     /** 
  110.      * 开始播放 
  111.      * 
  112.      * @param msec 播放初始位置 
  113.      */  
  114.     protected void video_play(final int msec) {  
  115. //      // 获取视频文件地址  
  116.         try {  
  117.             mediaPlayer = new MediaPlayer();  
  118.             //设置音频流类型  
  119.             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  120.             // 设置播放的视频源  
  121.             AssetFileDescriptor fd = this.getAssets().openFd("Perspective.mp4");  
  122.             mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),  
  123.                     fd.getLength());  
  124.             // 设置显示视频的SurfaceHolder  
  125.             mediaPlayer.setDisplay(surfaceview.getHolder());//这一步是关键,制定用于显示视频的SurfaceView对象(通过setDisplay())  
  126.   
  127.             mediaPlayer.prepareAsync();  
  128.             mediaPlayer.setOnPreparedListener(new OnPreparedListener() {  
  129.   
  130.                 @Override  
  131.                 public void onPrepared(MediaPlayer mp) {  
  132.                     mediaPlayer.start();  
  133.   
  134.                     // 按照初始位置播放  
  135.                     mediaPlayer.seekTo(msec);  
  136.                     // 设置进度条的最大进度为视频流的最大播放时长  
  137.                     seekBar.setMax(mediaPlayer.getDuration());  
  138.                     // 开始线程,更新进度条的刻度  
  139.                     new Thread() {  
  140.   
  141.                         @Override  
  142.                         public void run() {  
  143.                             try {  
  144.                                 isPlaying = true;  
  145.                                 while (isPlaying) {  
  146.                                     int current = mediaPlayer  
  147.                                             .getCurrentPosition();  
  148.                                     seekBar.setProgress(current);  
  149.   
  150.                                     sleep(500);  
  151.                                 }  
  152.                             } catch (Exception e) {  
  153.                                 e.printStackTrace();  
  154.                             }  
  155.                         }  
  156.                     }.start();  
  157.   
  158.                     start.setEnabled(false);  
  159.                 }  
  160.             });  
  161.             mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {  
  162.   
  163.                 @Override  
  164.                 public void onCompletion(MediaPlayer mp) {  
  165.                     // 在播放完毕被回调  
  166.                     start.setEnabled(true);  
  167.                 }  
  168.             });  
  169.   
  170.             mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {  
  171.   
  172.                 @Override  
  173.                 public boolean onError(MediaPlayer mp, int what, int extra) {  
  174.                     // 发生错误重新播放  
  175.                     video_play(0);  
  176.                     isPlaying = false;  
  177.                     return false;  
  178.                 }  
  179.             });  
  180.         } catch (Exception e) {  
  181.             e.printStackTrace();  
  182.         }  
  183.   
  184.     }  
  185.   
  186.   
  187.     /** 
  188.      * 暂停或继续 
  189.      */  
  190.     protected void pause() {  
  191.         if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
  192.             mediaPlayer.pause();  
  193.         }  
  194.   
  195.     }  
  196.   
  197.   
  198.   
  199.   
  200. }  


activity_main.xml:

 

 

[html]  view plain  copy
 
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <FrameLayout  
  7.         android:layout_width="match_parent"  
  8.         android:layout_height="220dp">  
  9.   
  10.         <SurfaceView  
  11.             android:id="@+id/surfaceView"  
  12.             android:layout_width="match_parent"  
  13.             android:layout_height="220dp"/>  
  14.   
  15.         <LinearLayout  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="30dp"  
  18.             android:layout_gravity="top"  
  19.             android:orientation="horizontal"  
  20.             android:background="@drawable/video_top">  
  21.   
  22.             <!--android:alpha="0.3"-->  
  23.   
  24.             <ImageButton  
  25.                 android:id="@+id/video_back"  
  26.                 android:layout_width="15dp"  
  27.                 android:layout_height="18dp"  
  28.                 android:background="@drawable/video_back"  
  29.                 android:layout_gravity="center"  
  30.                 android:layout_marginLeft="20dp"></ImageButton>  
  31.   
  32.             <ImageButton  
  33.                 android:id="@+id/video_share"  
  34.                 android:layout_width="25dp"  
  35.                 android:layout_height="15dp"  
  36.                 android:background="@drawable/video_share"  
  37.                 android:layout_gravity="center"  
  38.                 android:layout_marginLeft="280dp"  
  39.   
  40.                 />  
  41.   
  42.         </LinearLayout>  
  43.   
  44.   
  45.   
  46.   
  47.   
  48.         <LinearLayout  
  49.             android:layout_width="match_parent"  
  50.             android:layout_height="30dp"  
  51.             android:layout_gravity="bottom"  
  52.             android:orientation="horizontal"  
  53.             android:background="@drawable/video_bottom">  
  54.   
  55.         <ImageButton  
  56.             android:id="@+id/video_start"  
  57.             android:layout_width="18dp"  
  58.             android:layout_height="wrap_content"  
  59.             android:background="@drawable/video_start"  
  60.             android:layout_gravity="center"  
  61.             android:layout_marginLeft="20dp">  
  62.   
  63.         </ImageButton>  
  64.   
  65.   
  66.   
  67.   
  68.   
  69.   
  70.             <SeekBar  
  71.                 android:id="@+id/seekBar"  
  72.                 android:layout_width="250dp"  
  73.                 android:layout_height="wrap_content"  
  74.                 android:layout_gravity="center"  
  75.                 android:layout_marginLeft="20dp"  
  76.                 android:progressDrawable="@drawable/seekbar_style"  
  77.                 android:thumb="@drawable/seekbar_thumb"  
  78.                 android:maxHeight="8dp"  
  79.                 android:minHeight="8dp"  
  80.   
  81.                 />  
  82.   
  83.         <ImageButton  
  84.             android:id="@+id/video_pause"  
  85.             android:layout_width="15dp"  
  86.             android:layout_height="18dp"  
  87.             android:background="@drawable/video_pause"  
  88.             android:layout_gravity="center"  
  89.             android:layout_marginLeft="20dp"  
  90.             />  
  91.   
  92.   
  93.     </LinearLayout>  
  94.   
  95.   
  96.     </FrameLayout>  
  97.   
  98.   
  99. </RelativeLayout>  

 

 

 

 

 

对进度条的布局优化:

 

[html]  view plain  copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <layer-list  
  3.     xmlns:android="http://schemas.android.com/apk/res/android">  
  4.     <item >  
  5.         <shape>  
  6.             <solid android:color="#c6c6c6" />  
  7.         </shape>  
  8.     </item>  
  9.     <item>  
  10.         <clip>  
  11.             <shape>  
  12.                 <solid android:color="#06a7fa" />  
  13.             </shape>  
  14.         </clip>  
  15.     </item>  
  16. </layer-list>  


对进度点的布局优化:

 

 

[html]  view plain  copy
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <!-- 按下状态 -->  
  4.     <item  
  5.         android:state_pressed="true"  
  6.         android:drawable="@drawable/video_seekbar_after" />  
  7.   
  8.     <!-- 普通无焦点状态 -->  
  9.     <item  
  10.         android:state_focused="false"  
  11.         android:state_pressed="false"  
  12.         android:drawable="@drawable/video_seekbar_before" />  
  13.   
  14. </selector>   

 

你好,关于使用MediaPlayerSurfaceView播放视频,可以按照以下步骤进行: 1. 在XML布局文件中添加SurfaceView控件: ``` <SurfaceView android:id="@+id/surface_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Java代码中获取SurfaceView控件,创建MediaPlayer对象,并设置相关监听器: ``` // 获取SurfaceView控件 SurfaceView surfaceView = findViewById(R.id.surface_view); // 创建MediaPlayer对象 MediaPlayer mediaPlayer = new MediaPlayer(); // 设置SurfaceView作为MediaPlayer的显示界面 mediaPlayer.setDisplay(surfaceView.getHolder()); // 设置MediaPlayer的一些监听器 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 视频准备完成后自动播放 mp.start(); } }); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 视频播放完成后的处理 } }); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { // MediaPlayer出错时的处理 return false; } }); ``` 3. 设置MediaPlayer的数据源、准备视频等操作: ``` try { // 设置MediaPlayer的数据源 mediaPlayer.setDataSource("video_path"); // 准备视频 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } ``` 4. 在需要的地方控制视频播放、暂停、停止操作: ``` // 播放视频 mediaPlayer.start(); // 暂停视频 mediaPlayer.pause(); // 停止视频 mediaPlayer.stop(); ``` 希望以上步骤能帮到您。若有疑问,请随时咨询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值