mediaPlayer+surefacce播放视频

本文介绍了一个使用Android系统的MediaPlayer组件实现视频播放的应用案例。该应用通过SurfaceView显示视频,并针对不同情况调整了视频尺寸以适应屏幕。此外,还详细展示了如何设置各种监听器来处理视频播放过程中的事件。
原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://mikewang.blog.51cto.com/3826268/813611
package com.mike.activity; 

import java.io.IOException; 

import android.app.Activity; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.media.MediaPlayer.OnBufferingUpdateListener; 
import android.media.MediaPlayer.OnCompletionListener; 
import android.media.MediaPlayer.OnErrorListener; 
import android.media.MediaPlayer.OnPreparedListener; 
import android.media.MediaPlayer.OnSeekCompleteListener; 
import android.media.MediaPlayer.OnVideoSizeChangedListener; 
import android.media.MediaRecorder; 
import android.media.MediaRecorder.OnInfoListener; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 
import android.util.Log; 
import android.view.Display; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.widget.LinearLayout; 

public  class VedioPlayByMediaPlayerDemoActivity  extends Activity  implements 
    OnCompletionListener, OnErrorListener, OnPreparedListener, 
    OnSeekCompleteListener, OnVideoSizeChangedListener, 
    SurfaceHolder.Callback, android.media.MediaPlayer.OnInfoListener, 
    OnBufferingUpdateListener { 
   private SurfaceView mSurfaceView; 
   private SurfaceHolder mSurfaceHolder; 
   private MediaPlayer mMediaPlayer; 
   private  int mVideoWidth = 0; 
   private  int mVideoHeight = 0; 

   private  boolean readyToPlay =  false

   public  static  final String TAG =  "MEDIA_PLAY_VEDIO_PLAY"

   /** Called when the activity is first created. */ 
  @Override 
   public  void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    Log.d( "path""path is :" + Environment.getExternalStorageDirectory()); 

    mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1); 
    mSurfaceHolder = mSurfaceView.getHolder(); 

    mSurfaceHolder.addCallback( this); // 添加到回调监听器 

    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 需要确保底层表面是一个推送缓冲区表面,需要将其应用于视频播放和摄像头预览 

    mMediaPlayer =  new MediaPlayer(); 

     // 设置各种监听 
    mMediaPlayer.setOnCompletionListener( this); 
    mMediaPlayer.setOnErrorListener( this); 
    mMediaPlayer.setOnInfoListener( this); 
    mMediaPlayer.setOnPreparedListener( this); 
    mMediaPlayer.setOnSeekCompleteListener( this); 
    mMediaPlayer.setOnVideoSizeChangedListener( this); 
    mMediaPlayer.setOnBufferingUpdateListener( this); 

    String path = Environment.getExternalStorageDirectory() 
        +  "/Movies/vedio1.mp4"

     try { 
      mMediaPlayer.setDataSource(path); // 此处可能抛出异常 
    }  catch (IllegalArgumentException e) { 
       // TODO Auto-generated catch block 
      Log.v(TAG, e.getMessage()); 
       this.finish(); 
    }  catch (IllegalStateException e) { 
       // TODO Auto-generated catch block 
      Log.v(TAG, e.getMessage()); 
       this.finish(); 
    }  catch (IOException e) { 
       // TODO Auto-generated catch block 
      Log.v(TAG, e.getMessage()); 
       this.finish(); 
    } 

    mMediaPlayer.setDisplay(mSurfaceHolder); // mediaPlayer将在其表面播放 

     try { 
      mMediaPlayer.prepare(); // prepare方法是同步的(synchronous),所以可能会阻塞,prepareAsync()是异步方法(asynchronous)。 
    }  catch (IllegalStateException e) { 
       // TODO Auto-generated catch block 
      Log.v(TAG, e.getMessage()); 
       this.finish(); 
    }  catch (IOException e) { 
       // TODO Auto-generated catch block 
      Log.v(TAG, e.getMessage()); 
       this.finish(); 
    } 

     // 设置表面大小以匹配视频或显示器大小,取决于那个大小较小 
    mVideoWidth = mMediaPlayer.getVideoWidth(); 
    mVideoHeight = mMediaPlayer.getVideoHeight(); 
     
     int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); 
     int screenHeight = getWindowManager().getDefaultDisplay().getHeight(); 

     if (mVideoWidth > screenWidth 
        || mVideoHeight > getWindowManager().getDefaultDisplay() 
        .getHeight()) { //如果视频宽度大于显示器大小,得到比率 
         float heightRatio = ( float)mVideoHeight / ( float)screenHeight; 
         float widthRatio = ( float)mVideoWidth / ( float)screenWidth; 
         
         if (heightRatio > 1 || widthRatio >1) { //只需宽或高一个方向超出即可 
            
          if (heightRatio > widthRatio) { //以高为准 
            mVideoHeight = ( int) Math.ceil(( float)mVideoHeight / ( float)heightRatio); 
            mVideoWidth = ( int) Math.ceil(( float)mVideoWidth / ( float)heightRatio);    
         }  else { //以宽为准 
            mVideoHeight = ( int) Math.ceil(( float)mVideoHeight / ( float)widthRatio); 
            mVideoWidth = ( int) Math.ceil(( float)mVideoWidth / ( float)widthRatio); 
         } 
            
        } 
        
    } 
     
     
     //设置显示大小---- 
    mSurfaceView.setLayoutParams( new LinearLayout.LayoutParams(mVideoWidth, mVideoHeight)); 

    mMediaPlayer.start(); //播放视频 

  } 

   public  void surfaceChanged(SurfaceHolder holder,  int format,  int width, 
       int height) { // 当SurfaceView的底层表面的宽度,高度或者其他参数发生变化时,将调用SurfaceChanged方法 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "surfaceChanged"); 

  } 

   public  void surfaceCreated(SurfaceHolder holder) { // 因为实现了SurfaceHolder.Callback,并将其指定为回调监听器,所以将触发Surface的3个方法 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "surfaceCreated"); 
  } 

   public  void surfaceDestroyed(SurfaceHolder holder) { // 当Surface表面销毁时,将调用SurfaceDestroy方法
     // TODO Auto-generated method stub 
    Log.v(TAG,  "surfaceDestroyed"); 

  } 

   public  void onVideoSizeChanged(MediaPlayer mp,  int width,  int height) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onVideoSizeChanged"); 

  } 

   public  void onSeekComplete(MediaPlayer mp) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onSeekComplete"); 

  } 

   public  void onPrepared(MediaPlayer mp) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onPrepared"); 

  } 

   public  boolean onError(MediaPlayer mp,  int what,  int extra) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onError"); 

     if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) { 
      Log.v(TAG,  "MEDIA_ERROR_SERVER_DIED"); 
      mMediaPlayer.reset(); // 可调用此方法重置 
    }  else  if (what == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { 
      Log.v(TAG,  "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK"); 
    }  else  if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) { 
      Log.v(TAG,  "MEDIA_ERROR_UNKNOWN"); 
    } 

     return  false; // 返回false,表示错误没有被处理 
  } 

   public  void onCompletion(MediaPlayer mp) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onCompletion"); 
     this.finish(); 
  } 

   public  void onBufferingUpdate(MediaPlayer arg0,  int arg1) { 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onBufferingUpdate"); 

  } 

   public  boolean onInfo(MediaPlayer mp,  int what,  int extra) { // 当出现关于播放媒体的特定信息需要发出警告时,将调用此方法 
     // TODO Auto-generated method stub 
    Log.v(TAG,  "onInfo"); 

     switch (what) { 
     case MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING: // 当文件中的音频和视频数据不正确的交错时,将触发如下操作。 
                             // 在一个正确交错的媒体文件中,音频和视频样本依序排列,从而使得播放能够有效平稳的进行。 
      Log.v(TAG,  "MEDIA_INFO_BAD_INTERLEAVING extar is :" + extra); 
       break
     case MediaPlayer.MEDIA_INFO_METADATA_UPDATE: // 当心的元数据可用时,将触发它,android 
                           // 2.0以上版本可用。 
      Log.v(TAG,  "MEDIA_INFO_METADATA_UPDATE extar is :" + extra); 
       break
     case MediaPlayer.MEDIA_INFO_NOT_SEEKABLE: // 媒体不能正确定位,意味着它可能是一个在线流 
      Log.v(TAG,  "MEDIA_INFO_NOT_SEEKABLE extar is :" + extra); 
       break
     case MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING: // 当无法播放视频时,可能是将要播放视频,但是视频太复杂 
      Log.v(TAG,  "MEDIA_INFO_VIDEO_TRACK_LAGGING extar is :" + extra); 
       break
     case MediaPlayer.MEDIA_INFO_UNKNOWN: 
      Log.v(TAG,  "MEDIA_INFO_UNKNOWN extar is :" + extra); 
       break
    } 

     return  false
  } 

}

本文出自 “小新专栏” 博客,请务必保留此出处http://mikewang.blog.51cto.com/3826268/813611

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值