本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!

       上次讲解了MediaPlayer播放网络音频, 介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法,这次再讲解MediaPlayer播放网络视频。播放网络视频比播放网络音频多需要 一个SurfaceView而已,已经熟悉MediaPlayer播放网络音频之后,相信大家对播放网络视频也能很快地掌握。先来看看本文程序运行截图:

本文程序的视频来自http://daily3gp.com,大家可以替换程序中的视频链接,试试其他影片。

main.xml的源码如下:

 

 
   
  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"   
  3.     android:layout_height="fill_parent" android:layout_width="fill_parent">   
  4.     <SurfaceView android:id="@+id/surfaceView1"   
  5.         android:layout_height="fill_parent" android:layout_width="fill_parent"></SurfaceView>   
  6.     <LinearLayout android:layout_height="wrap_content"   
  7.         android:layout_width="fill_parent" android:layout_gravity="bottom"   
  8.         android:orientation="vertical">   
  9.         <LinearLayout android:orientation="horizontal"   
  10.             android:layout_gravity="center_horizontal" android:layout_marginTop="4.0dip"   
  11.             android:layout_height="wrap_content" android:layout_width="wrap_content">   
  12.             <Button android:layout_width="wrap_content"   
  13.                 android:layout_height="wrap_content" android:id="@+id/btnPlayUrl"   
  14.                 android:text="播放网络视频"></Button>   
  15.             <Button android:layout_height="wrap_content" android:id="@+id/btnPause"   
  16.                 android:text="暂停" android:layout_width="80dip"></Button>   
  17.             <Button android:layout_height="wrap_content"   
  18.                 android:layout_width="80dip" android:text="停止" android:id="@+id/btnStop"></Button>   
  19.         </LinearLayout>   
  20.         <LinearLayout android:orientation="horizontal"   
  21.             android:layout_width="fill_parent" android:layout_height="wrap_content"   
  22.             android:layout_marginBottom="20dip">   
  23.             <SeekBar android:paddingRight="10dip" android:layout_gravity="center_vertical"   
  24.                 android:paddingLeft="10dip" android:layout_weight="1.0"   
  25.                 android:layout_height="wrap_content" android:layout_width="wrap_content"   
  26.                 android:id="@+id/skbProgress" android:max="100"></SeekBar>   
  27.         </LinearLayout>   
  28.     </LinearLayout>   
  29. </FrameLayout>   

Player.java 是本文的核心,Player.java实现了“进度条更新”、“数据缓冲”、“SurfaceHolder生命周期”等功能,其中 “SurfaceHolder生命周期”是视频与音频播放的最大区别,通过surfaceCreated()、surfaceDestroyed()、 surfaceChanged()可以创建/释放某些资源。下面这个地方需要注意一下:

 
   
  1. videoWidth = mediaPlayer.getVideoWidth();   
  2.         videoHeight = mediaPlayer.getVideoHeight();   
  3.         if (videoHeight != 0 && videoWidth != 0) {   
  4.             arg0.start();   
  5.         }   

 

有些视频是android播放器不能播放的,不能播放时videoHeight=0,videoWidth=0,以此来判断是否播放视频。

Player.java源码如下:

 

 
   
  1. package com.videoplayer;   
  2.    
  3.    
  4. import java.io.IOException;   
  5. import java.util.Timer;   
  6. import java.util.TimerTask;   
  7. import android.media.AudioManager;   
  8. import android.media.MediaPlayer;   
  9. import android.media.MediaPlayer.OnBufferingUpdateListener;   
  10. import android.media.MediaPlayer.OnCompletionListener;   
  11. import android.os.Handler;   
  12. import android.os.Message;   
  13. import android.util.Log;   
  14. import android.view.SurfaceHolder;   
  15. import android.view.SurfaceView;   
  16. import android.widget.SeekBar;   
  17.    
  18. public class Player implements OnBufferingUpdateListener,   
  19.         OnCompletionListener, MediaPlayer.OnPreparedListener,   
  20.         SurfaceHolder.Callback {   
  21.     private int videoWidth;   
  22.     private int videoHeight;   
  23.     public MediaPlayer mediaPlayer;   
  24.     private SurfaceHolder surfaceHolder;   
  25.     private SeekBar skbProgress;   
  26.     private Timer mTimer=new Timer();   
  27.     public Player(SurfaceView surfaceView,SeekBar skbProgress)   
  28.     {   
  29.         this.skbProgress=skbProgress;   
  30.         surfaceHolder=surfaceView.getHolder();   
  31.         surfaceHolder.addCallback(this);   
  32.         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);   
  33.         mTimer.schedule(mTimerTask, 01000);   
  34.     }   
  35.        
  36.     /*******************************************************  
  37.      * 通过定时器和Handler来更新进度条  
  38.      ******************************************************/   
  39.     TimerTask mTimerTask = new TimerTask() {   
  40.         @Override   
  41.         public void run() {   
  42.             if(mediaPlayer==null)   
  43.                 return;   
  44.             if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {   
  45.                 handleProgress.sendEmptyMessage(0);   
  46.             }   
  47.         }   
  48.     };   
  49.        
  50.     Handler handleProgress = new Handler() {   
  51.         public void handleMessage(Message msg) {   
  52.    
  53.             int position = mediaPlayer.getCurrentPosition();   
  54.             int duration = mediaPlayer.getDuration();   
  55.                
  56.             if (duration > 0) {   
  57.                 long pos = skbProgress.getMax() * position / duration;   
  58.                 skbProgress.setProgress((int) pos);   
  59.             }   
  60.         };   
  61.     };   
  62.     //*****************************************************   
  63.        
  64.     public void play()   
  65.     {   
  66.         mediaPlayer.start();   
  67.     }   
  68.        
  69.     public void playUrl(String videoUrl)   
  70.     {   
  71.         try {   
  72.             mediaPlayer.reset();   
  73.             mediaPlayer.setDataSource(videoUrl);   
  74.             mediaPlayer.prepare();//prepare之后自动播放   
  75.             //mediaPlayer.start();   
  76.         } catch (IllegalArgumentException e) {   
  77.             // TODO Auto-generated catch block   
  78.             e.printStackTrace();   
  79.         } catch (IllegalStateException e) {   
  80.             // TODO Auto-generated catch block   
  81.             e.printStackTrace();   
  82.         } catch (IOException e) {   
  83.             // TODO Auto-generated catch block   
  84.             e.printStackTrace();   
  85.         }   
  86.     }   
  87.    
  88.        
  89.     public void pause()   
  90.     {   
  91.         mediaPlayer.pause();   
  92.     }   
  93.        
  94.     public void stop()   
  95.     {   
  96.         if (mediaPlayer != null) {    
  97.             mediaPlayer.stop();   
  98.             mediaPlayer.release();    
  99.             mediaPlayer = null;    
  100.         }    
  101.     }   
  102.        
  103.     @Override   
  104.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {   
  105.         Log.e("mediaPlayer""surface changed");   
  106.     }   
  107.    
  108.     @Override   
  109.     public void surfaceCreated(SurfaceHolder arg0) {   
  110.         try {   
  111.             mediaPlayer = new MediaPlayer();   
  112.             mediaPlayer.setDisplay(surfaceHolder);   
  113.             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);   
  114.             mediaPlayer.setOnBufferingUpdateListener(this);   
  115.             mediaPlayer.setOnPreparedListener(this);   
  116.         } catch (Exception e) {   
  117.             Log.e("mediaPlayer""error", e);   
  118.         }   
  119.         Log.e("mediaPlayer""surface created");   
  120.     }   
  121.    
  122.     @Override   
  123.     public void surfaceDestroyed(SurfaceHolder arg0) {   
  124.         Log.e("mediaPlayer""surface destroyed");   
  125.     }   
  126.    
  127.        
  128.     @Override   
  129.     /**   
  130.      * 通过onPrepared播放   
  131.      */   
  132.     public void onPrepared(MediaPlayer arg0) {   
  133.         videoWidth = mediaPlayer.getVideoWidth();   
  134.         videoHeight = mediaPlayer.getVideoHeight();   
  135.         if (videoHeight != 0 && videoWidth != 0) {   
  136.             arg0.start();   
  137.         }   
  138.         Log.e("mediaPlayer""onPrepared");   
  139.     }   
  140.    
  141.     @Override   
  142.     public void onCompletion(MediaPlayer arg0) {   
  143.         // TODO Auto-generated method stub   
  144.            
  145.     }   
  146.    
  147.     @Override   
  148.     public void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress) {   
  149.         skbProgress.setSecondaryProgress(bufferingProgress);   
  150.         int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();   
  151.         Log.e(currentProgress+"% play", bufferingProgress + "% buffer");   
  152.            
  153.     }   
  154.    
  155. }   

test_videoplayer.java是主程序,负责调用Player类,其中关键部分是SeekBarChangeEvent这个SeekBar拖动的事件:SeekBar 的Progress是0~SeekBar.getMax()之内的数,而MediaPlayer.seekTo()的参数是 0~MediaPlayer.getDuration()之内数,所以MediaPlayer.seekTo()的参数是 (progress/seekBar.getMax())*MediaPlayer.getDuration()。

 

test_videoplayer.java源码如下:

 

 

 
   
  1. package com.videoplayer;   
  2.    
  3. import android.app.Activity;   
  4. import android.content.pm.ActivityInfo;   
  5. import android.net.Uri;   
  6. import android.os.Bundle;   
  7. import android.util.Log;   
  8. import android.view.SurfaceView;   
  9. import android.view.View;   
  10. import android.view.View.OnClickListener;   
  11. import android.widget.Button;   
  12. import android.widget.SeekBar;   
  13.    
  14. public class test_videoplayer extends Activity {   
  15.     private SurfaceView surfaceView;   
  16.     private Button btnPause, btnPlayUrl, btnStop;   
  17.     private SeekBar skbProgress;   
  18.     private Player player;   
  19.    
  20.     /** Called when the activity is first created. */   
  21.     @Override   
  22.     public void onCreate(Bundle savedInstanceState) {   
  23.         super.onCreate(savedInstanceState);   
  24.         setContentView(R.layout.main);   
  25.         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);   
  26.         surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView1);   
  27.    
  28.         btnPlayUrl = (Button) this.findViewById(R.id.btnPlayUrl);   
  29.         btnPlayUrl.setOnClickListener(new ClickEvent());   
  30.    
  31.         btnPause = (Button) this.findViewById(R.id.btnPause);   
  32.         btnPause.setOnClickListener(new ClickEvent());   
  33.    
  34.         btnStop = (Button) this.findViewById(R.id.btnStop);   
  35.         btnStop.setOnClickListener(new ClickEvent());   
  36.    
  37.         skbProgress = (SeekBar) this.findViewById(R.id.skbProgress);   
  38.         skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());   
  39.         player = new Player(surfaceView, skbProgress);   
  40.    
  41.     }   
  42.    
  43.     class ClickEvent implements OnClickListener {   
  44.    
  45.         @Override   
  46.         public void onClick(View arg0) {   
  47.             if (arg0 == btnPause) {   
  48.                 player.pause();   
  49.             } else if (arg0 == btnPlayUrl) {   
  50.                 String url="http://daily3gp.com/vids/family_guy_penis_car.3gp";   
  51.                 player.playUrl(url);   
  52.             } else if (arg0 == btnStop) {   
  53.                 player.stop();   
  54.             }   
  55.    
  56.         }   
  57.     }   
  58.    
  59.     class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {   
  60.         int progress;   
  61.    
  62.         @Override   
  63.         public void onProgressChanged(SeekBar seekBar, int progress,   
  64.                 boolean fromUser) {   
  65.             // 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()   
  66.             this.progress = progress * player.mediaPlayer.getDuration()   
  67.                     / seekBar.getMax();   
  68.         }   
  69.    
  70.         @Override   
  71.         public void onStartTrackingTouch(SeekBar seekBar) {   
  72.    
  73.         }   
  74.    
  75.         @Override   
  76.         public void onStopTrackingTouch(SeekBar seekBar) {   
  77.             // seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字   
  78.             player.mediaPlayer.seekTo(progress);   
  79.         }   
  80.     }   
  81.    
  82. }