MediaPlayer + SurfaceView 来实现 视频播放

转自:http://blog.csdn.net/jiahui524/article/details/7108358


步骤: 

 mediaPlayer+ surfaceView 例子的步骤:
 1,创建一个MediaPlayer,并创建三个按钮
 2, 创建surfaceView,并设置surfaceView的getHolder.setType和getHolder.addCallback()
 3,在addCallback的三个函数中,这里是如果在播放中建立的,则把positon=0 ,然后重新开始。
 4,在按钮中设置mediaplayer的播放,大概是:
    mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置需要播放的视频
mediaPlayer.setDataSource("/mnt/sdcard/vid320X240.3gp");
//把视频画面输出到SurfaceView
mediaPlayer.setDisplay(surfaceView.getHolder());   ///关键 的地方!!!!!!
mediaPlayer.prepare();
//播放
mediaPlayer.start();
 

xml源代码:(注意需要三个png格式的图片,更改名字为play.png pause.png stop.png)

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <SurfaceView  
  8.         android:id="@+id/surfaceView"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="360px" />  
  11.   
  12.     <LinearLayout  
  13.         android:layout_width="fill_parent"  
  14.         android:layout_height="wrap_content"  
  15.         android:gravity="center_horizontal"  
  16.         android:orientation="horizontal" >  
  17.   
  18.         <ImageButton  
  19.             android:id="@+id/btnplay"  
  20.             android:layout_width="wrap_content"  
  21.             android:layout_height="wrap_content"  
  22.             android:src="@drawable/play" />  
  23.   
  24.         <ImageButton  
  25.             android:id="@+id/btnpause"  
  26.             android:layout_width="wrap_content"  
  27.             android:layout_height="wrap_content"  
  28.             android:src="@drawable/pause" />  
  29.   
  30.         <ImageButton  
  31.             android:id="@+id/btnstop"  
  32.             android:layout_width="wrap_content"  
  33.             android:layout_height="wrap_content"  
  34.             android:src="@drawable/stop" />  
  35.     </LinearLayout>  
  36.   
  37. </LinearLayout>  

java  代码:
  1. package com.example.tstmediaplaycontroller2;  
  2. /* 
  3. import android.os.Bundle; 
  4. import android.app.Activity; 
  5. import android.view.Menu; 
  6. import android.view.MenuItem; 
  7. import android.support.v4.app.NavUtils; 
  8.  
  9. public class MainActivity extends Activity { 
  10.  
  11.     @Override 
  12.     public void onCreate(Bundle savedInstanceState) { 
  13.         super.onCreate(savedInstanceState); 
  14.         setContentView(R.layout.activity_main); 
  15.     } 
  16.  
  17.     @Override 
  18.     public boolean onCreateOptionsMenu(Menu menu) { 
  19.         getMenuInflater().inflate(R.menu.activity_main, menu); 
  20.         return true; 
  21.     } 
  22.  
  23.      
  24. }*/  
  25. import android.app.Activity;  
  26. import android.media.AudioManager;  
  27. import android.media.MediaPlayer;  
  28. import android.os.Bundle;  
  29. import android.view.SurfaceHolder;  
  30. import android.view.SurfaceHolder.Callback;  
  31. import android.view.SurfaceView;  
  32. import android.view.View;  
  33. import android.view.View.OnClickListener;  
  34. import android.widget.Button;  
  35. import android.widget.ImageButton;  
  36. import android.widget.Toast;  
  37.   
  38. public class MainActivity extends Activity  implements OnClickListener{  
  39.   
  40.     ImageButton btnplay, btnstop, btnpause;  
  41.     SurfaceView surfaceView;  
  42.     MediaPlayer mediaPlayer;  
  43.     int position;  
  44.   
  45.     public void onCreate(Bundle savedInstanceState) {  
  46.         super.onCreate(savedInstanceState);  
  47.         setContentView(R.layout.activity_main);   
  48.         btnplay=(ImageButton)this.findViewById(R.id.btnplay);  
  49.         btnstop=(ImageButton)this.findViewById(R.id.btnstop);  
  50.         btnpause=(ImageButton)this.findViewById(R.id.btnpause);  
  51.           
  52.         btnstop.setOnClickListener(this);  
  53.         btnplay.setOnClickListener(this);  
  54.         btnpause.setOnClickListener(this);  
  55.           
  56.         mediaPlayer=new MediaPlayer();  
  57.         surfaceView=(SurfaceView) this.findViewById(R.id.surfaceView);  
  58.       
  59.         //设置SurfaceView自己不管理的缓冲区  
  60.         surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);         
  61.         surfaceView.getHolder().addCallback(new Callback() {          
  62.             @Override  
  63.             public void surfaceDestroyed(SurfaceHolder holder) {  
  64.           
  65.             }  
  66.           
  67.             @Override  
  68.             public void surfaceCreated(SurfaceHolder holder) {  
  69.                 if (position>0) {  
  70.                     try {  
  71.                         //开始播放  
  72.                           
  73.                         play();  
  74.                           
  75.                         //并直接从指定位置开始播放  
  76.                         mediaPlayer.seekTo(position);  
  77.                         position=0;                       
  78.                     } catch (Exception e) {  
  79.                         // TODO: handle exception  
  80.                     }  
  81.                 }  
  82.                 System.out.println("surface create .............xxxxxxxxxxxxxxxx");  
  83.                   
  84.             }             
  85.             @Override  
  86.             public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  87.                     int height) {  
  88.   
  89.             }  
  90.         });       
  91.     }  
  92.     @Override  
  93.     public void onClick(View v)   
  94.     {     
  95.         switch (v.getId()) {  
  96.         case R.id.btnplay:  
  97.             play();  
  98.             break;  
  99.               
  100.         case R.id.btnpause:  
  101.             if (mediaPlayer.isPlaying())   
  102.             {  
  103.                 mediaPlayer.pause();  
  104.             }  
  105.             else  
  106.             {  
  107.                 mediaPlayer.start();  
  108.             }  
  109.             break;  
  110.   
  111.         case R.id.btnstop:  
  112.             if (mediaPlayer.isPlaying()) {  
  113.                 mediaPlayer.stop();  
  114.             }  
  115.               
  116.             break;  
  117.         default:  
  118.             break;  
  119.         }  
  120.   
  121.     }  
  122.     @Override  
  123.     protected void onPause() {    
  124.         //先判断是否正在播放  
  125.         if (mediaPlayer.isPlaying()) {  
  126.             //如果正在播放我们就先保存这个播放位置  
  127.             position=mediaPlayer.getCurrentPosition()  
  128.                     ;  
  129.             mediaPlayer.stop();  
  130.         }  
  131.         super.onPause();  
  132.     }  
  133.   
  134.     private void play() {  
  135.         try {  
  136.             mediaPlayer.reset();  
  137.             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  138.             //设置需要播放的视频  
  139.             mediaPlayer.setDataSource("/mnt/sdcard/vid320X240.3gp");  
  140.             //把视频画面输出到SurfaceView  
  141.             mediaPlayer.setDisplay(surfaceView.getHolder());  
  142.             mediaPlayer.prepare();  
  143.             //播放  
  144.             mediaPlayer.start();      
  145.             Toast.makeText(this"开始播放!", Toast.LENGTH_LONG).show();  
  146.         } catch (Exception e) {  
  147.             // TODO: handle exception  
  148.         }  
  149.     }  
  150. }  



注:

MediaPlayer主要用于播放音频,它是没有提供输出图像的输出界面,这时我们就用到了SurfaceView控件,将它与MediaPlayer结合起来,就能达到了视频的输出了。首先来了SurfaceView这个控件类

SurfaceView类


构造方法

方法名称

描述

public SurfaceView(Context context)

通过Context创建SurfaceView对象

public SurfaceView(Context context, AttributeSet attrs)

通过Context对象和AttributeSet创建SurfaceView对象

public SurfaceView(Context context, AttributeSet attrs, int defStyle)

通过Context对象和AttributeSet创建并可以指定样式,SurfaceView对象

 

常用方法

方法名称

描述

public SurfaceHolder getHolder ()

得到SurfaceHolder对象用于管理SurfaceView

public void setVisibility (int visibility)

设置是否可见,其值可以是VISIBLE, INVISIBLE, GONE.

 

SurfaceHolder


它是一个接口,用于管理SurfaceView。里面有两个常用的内部接口SurfaceHolder.Callback,SurfaceHolder.Callback2而Callback2是实现于Callback的

常用方法

方法名称

描述

public abstract void addCallback (SurfaceHolder.Callback callback)

添加一个Callback对象监听SurfaceView的变化

public abstract void removeCallback (SurfaceHolder.Callback callback)

移除Callback

public abstract void setType (int type)

设置SurfaceView的控制方式

public abstract Canvas lockCanvas ()

锁定整个SurfaceView对象,获取该Surface上的Canvas

public abstract Canvas lockCanvas (Rect dirty)

锁定SurfaceView上Rect划分的区域,获取该Surface上的Canvas

public abstract void unlockCanvasAndPost (Canvas canvas)

调用该方法,之前所绘制的图形还处于缓冲之中,下一次的lockCanvas()方法锁定的区域可能会“遮挡”它

 

SurfaceHolder.CallBack


在Callback里有三个抽象方法

方法名称

描述

public abstract void surfaceChanged (SurfaceHolder holder, int format, int width, int height)

SurfaceView改变时触发

public abstract void surfaceCreated (SurfaceHolder holder)

SurfaceView创建时触发

public abstract void surfaceDestroyed (SurfaceHolder holder)

SurfaceView销毁时触发

 

如何理解这几个类或者接口之间的关系?

这样理解:

SurfaceView它用于显示,SurfaceHolder就是用于用来管理这个显示的SurfaceView对象的,但在SurfaceHolder是怎么样去管理这个对象的呢?这就用到了SurfceHolder.addCallback()方法添加一个SurfaceHolder接口的内部接口的三个抽象方法用于管理或者说是用于监听SurfaceView。这样就达到了管理SurfaceView的目的。

 mediaPlayer 的方法是:


Valid and invalid states

Method Name Valid Sates Invalid States Comments
attachAuxEffect {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Error} This method must be called after setDataSource. Calling it does not change the object state.
getAudioSessionId any {} This method can be called in any state and calling it does not change the object state.
getCurrentPosition {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getDuration {Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getVideoHeight {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
getVideoWidth {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
isPlaying {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
pause {Started, Paused} {Idle, Initialized, Prepared, Stopped, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Paused state. Calling this method in an invalid state transfers the object to the Error state.
prepare {Initialized, Stopped} {Idle, Prepared, Started, Paused, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Prepared state. Calling this method in an invalid state throws an IllegalStateException.
prepareAsync {Initialized, Stopped} {Idle, Prepared, Started, Paused, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Preparing state. Calling this method in an invalid state throws an IllegalStateException.
release any {} After release(), the object is no longer available.
reset {Idle, Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} {} After reset(), the object is like being just created.
seekTo {Prepared, Started, Paused, PlaybackCompleted} {Idle, Initialized, Stopped, Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
setAudioSessionId {Idle} {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} This method must be called in idle state as the audio session ID must be known before calling setDataSource. Calling it does not change the object state.
setAudioStreamType {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method does not change the state. In order for the target audio stream type to become effective, this method must be called before prepare() or prepareAsync().
setAuxEffectSendLevel any {} Calling this method does not change the object state.
setDataSource {Idle} {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error} Successful invoke of this method in a valid state transfers the object to the Initialized state. Calling this method in an invalid state throws an IllegalStateException.
setDisplay any {} This method can be called in any state and calling it does not change the object state.
setSurface any {} This method can be called in any state and calling it does not change the object state.
setVideoScalingMode {Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} {Idle, Error} Successful invoke of this method does not change the state.
setLooping {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method in a valid state does not change the state. Calling this method in an invalid state transfers the object to the Error state.
isLooping any {} This method can be called in any state and calling it does not change the object state.
setOnBufferingUpdateListener any {} This method can be called in any state and calling it does not change the object state.
setOnCompletionListener any {} This method can be called in any state and calling it does not change the object state.
setOnErrorListener any {} This method can be called in any state and calling it does not change the object state.
setOnPreparedListener any {} This method can be called in any state and calling it does not change the object state.
setOnSeekCompleteListener any {} This method can be called in any state and calling it does not change the object state.
setScreenOnWhilePlaying any {} This method can be called in any state and calling it does not change the object state.
setVolume {Idle, Initialized, Stopped, Prepared, Started, Paused, PlaybackCompleted} {Error} Successful invoke of this method does not change the state.
setWakeMode any {} This method can be called in any state and calling it does not change the object state.
start {Prepared, Started, Paused, PlaybackCompleted} {Idle, Initialized, Stopped, Error} Successful invoke of this method in a valid state transfers the object to the Started state. Calling this method in an invalid state transfers the object to the Error state.
stop {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method in a valid state transfers the object to the Stopped state. Calling this method in an invalid state transfers the object to the Error state.
getTrackInfo {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
addTimedTextSource {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
selectTrack {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
deselectTrack {Prepared, Started, Stopped, Paused, PlaybackCompleted} {Idle, Initialized, Error} Successful invoke of this method does not change the state.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值