转自: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)
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <SurfaceView
- android:id="@+id/surfaceView"
- android:layout_width="fill_parent"
- android:layout_height="360px" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:orientation="horizontal" >
- <ImageButton
- android:id="@+id/btnplay"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/play" />
- <ImageButton
- android:id="@+id/btnpause"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/pause" />
- <ImageButton
- android:id="@+id/btnstop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/stop" />
- </LinearLayout>
- </LinearLayout>
java 代码:
- package com.example.tstmediaplaycontroller2;
- /*
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.support.v4.app.NavUtils;
- public class MainActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.activity_main, menu);
- return true;
- }
- }*/
- import android.app.Activity;
- import android.media.AudioManager;
- import android.media.MediaPlayer;
- import android.os.Bundle;
- import android.view.SurfaceHolder;
- import android.view.SurfaceHolder.Callback;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ImageButton;
- import android.widget.Toast;
- public class MainActivity extends Activity implements OnClickListener{
- ImageButton btnplay, btnstop, btnpause;
- SurfaceView surfaceView;
- MediaPlayer mediaPlayer;
- int position;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- btnplay=(ImageButton)this.findViewById(R.id.btnplay);
- btnstop=(ImageButton)this.findViewById(R.id.btnstop);
- btnpause=(ImageButton)this.findViewById(R.id.btnpause);
- btnstop.setOnClickListener(this);
- btnplay.setOnClickListener(this);
- btnpause.setOnClickListener(this);
- mediaPlayer=new MediaPlayer();
- surfaceView=(SurfaceView) this.findViewById(R.id.surfaceView);
- //设置SurfaceView自己不管理的缓冲区
- surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- surfaceView.getHolder().addCallback(new Callback() {
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- if (position>0) {
- try {
- //开始播放
- play();
- //并直接从指定位置开始播放
- mediaPlayer.seekTo(position);
- position=0;
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- System.out.println("surface create .............xxxxxxxxxxxxxxxx");
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- }
- });
- }
- @Override
- public void onClick(View v)
- {
- switch (v.getId()) {
- case R.id.btnplay:
- play();
- break;
- case R.id.btnpause:
- if (mediaPlayer.isPlaying())
- {
- mediaPlayer.pause();
- }
- else
- {
- mediaPlayer.start();
- }
- break;
- case R.id.btnstop:
- if (mediaPlayer.isPlaying()) {
- mediaPlayer.stop();
- }
- break;
- default:
- break;
- }
- }
- @Override
- protected void onPause() {
- //先判断是否正在播放
- if (mediaPlayer.isPlaying()) {
- //如果正在播放我们就先保存这个播放位置
- position=mediaPlayer.getCurrentPosition()
- ;
- mediaPlayer.stop();
- }
- super.onPause();
- }
- private void play() {
- try {
- mediaPlayer.reset();
- mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- //设置需要播放的视频
- mediaPlayer.setDataSource("/mnt/sdcard/vid320X240.3gp");
- //把视频画面输出到SurfaceView
- mediaPlayer.setDisplay(surfaceView.getHolder());
- mediaPlayer.prepare();
- //播放
- mediaPlayer.start();
- Toast.makeText(this, "开始播放!", Toast.LENGTH_LONG).show();
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- }
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. |