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

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

实现效果:

Android之视频播放使用MediaPlayer+SurfaceView代替ViedoView控件_第1张图片


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.               
  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>   

你可能感兴趣的:(Android之视频播放使用MediaPlayer+SurfaceView代替ViedoView控件)