ApiDemos学习知识点之media-MediaPlayer_Audio&MediaPlayer_Video(11)

时间:2022-01-01 09:26:37

该项目demo是通过从本地文件路径和资源raw文件加载音频。以及从不同路径加载视频的案例。

下面看下MediaPlayer_Audio部分音频加载的代码

public class MediaPlayerDemo_Audio extends Activity {

private static final String TAG = "MediaPlayerDemo";
private MediaPlayer mMediaPlayer;
private static final String MEDIA = "media";
private static final int LOCAL_AUDIO = 1;
private static final int STREAM_AUDIO = 2;
private static final int RESOURCES_AUDIO = 3;
private static final int LOCAL_VIDEO = 4;
private static final int STREAM_VIDEO = 5;
private String path;

private TextView tx;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
tx = new TextView(this);
setContentView(tx);
Bundle extras = getIntent().getExtras();
playAudio(extras.getInt(MEDIA));
}

private void playAudio(Integer media) {
try {
switch (media) {
case LOCAL_AUDIO:
/**
* 将路径变量设置为本地音频文件路径。
*/
path = "";
if (path == "") {
// 告诉用户提供一个音频文件URL
Toast.makeText(MediaPlayerDemo_Audio.this,
"Please edit MediaPlayer_Audio Activity, "
+ "and set the path variable to your audio file path."
+ " Your audio file must be stored on sdcard.",
Toast.LENGTH_LONG).show();

}
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(path);
mMediaPlayer.prepare();
mMediaPlayer.start();
break;
case RESOURCES_AUDIO:
/**
* 将音频文件上载到res / raw文件夹,并在mediaplayer . create()方法中提供它的resid。
*/
mMediaPlayer = MediaPlayer.create(this, R.raw.test_cbr);
mMediaPlayer.start();

}
tx.setText("Playing audio...");

} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}

}

@Override
protected void onDestroy() {
super.onDestroy();
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}

}
}
下面看下MediaPlayer_Video部分的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<SurfaceView android:id="@+id/surface"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
</SurfaceView>

</LinearLayout>
通过一个SurfaceView控件来进行视频的管理

  1. SurfaceView 就是带 Surface 的 view,它是一个 View,是 View 的子类,所以和其他 View 一样,可以在屏幕上展示东西接收用户输入,具有 View 的生命周期回调函数,如 onMeasure、onLayout、onDraw、onTouchEvent 等
  2. SurfaceView 带有独立的 Surface(独立与 window 的 surface),这可以让子线程在独立的 Surface 上面绘制东西,进行 SurfaceView 的界面绘制,这个子线程就叫做渲染线程,但是要让独立的 Surface 上面的东西在 View 上面展示出来,需要 post 一个消息给主线程,目的是把该 Surface 中 canvas 上的东西绘制到 View 的真正的画布上面(window 的 surface 的 canvas上),这样就可以把 UI 线程空闲出来处理用户的交互
  3. Surface 可能被销毁,它只在SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed() 之间有效,这只是说 Surface 创建和销毁的时候会回到前面两个方法,所以要确保渲染线程访问的是合法有效的 surface
  4. SurfaceHolder.CallBack 是通过 SurfaceView 的 SurfaceHolder 的 addCallback 来设置给 SurfaceHolder 的,让 SurfaceView 实现 CallBack 并设置给 SurfaceHolder,SurfaceView 就可以监听这个独立 Surface 的创建和销毁了。
再看一下MediaPlayer的常用方法介绍
方法:create(Context context, Uri uri) 
解释:静态方法,通过Uri创建一个多媒体播放器。 

方法:create(Context context, int resid) 
解释:静态方法,通过资源ID创建一个多媒体播放器 

方法:create(Context context, Uri uri, SurfaceHolder holder) 
解释:静态方法,通过Uri和指定 SurfaceHolder 【抽象类】 创建一个多媒体播放器 

方法: getCurrentPosition() 
解释:返回 Int, 得到当前播放位置 

方法: getDuration() 
解释:返回 Int,得到文件的时间 

方法:getVideoHeight() 
解释:返回 Int ,得到视频的高度 

方法:getVideoWidth() 
解释:返回 Int,得到视频的宽度 

方法:isLooping() 
解释:返回 boolean ,是否循环播放 

方法:isPlaying() 
解释:返回 boolean,是否正在播放 

方法:pause() 
解释:无返回值 ,暂停 

方法:prepare() 
解释:无返回值,准备同步 

方法:prepareAsync() 
解释:无返回值,准备异步 

方法:release() 
解释:无返回值,释放 MediaPlayer 对象 

方法:reset() 
解释:无返回值,重置 MediaPlayer 对象 

方法:seekTo(int msec) 
解释:无返回值,指定播放的位置(以毫秒为单位的时间) 

方法:setAudioStreamType(int streamtype) 
解释:无返回值,指定流媒体的类型 

方法:setDataSource(String path) 
解释:无返回值,设置多媒体数据来源【根据 路径】 

方法:setDataSource(FileDescriptor fd, long offset, long length) 
解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】 

方法:setDataSource(FileDescriptor fd) 
解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】 

方法:setDataSource(Context context, Uri uri) 
解释:无返回值,设置多媒体数据来源【根据 Uri】 

方法:setDisplay(SurfaceHolder sh) 
解释:无返回值,设置用 SurfaceHolder 来显示多媒体 

方法:setLooping(boolean looping) 
解释:无返回值,设置是否循环播放 

事件:setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener) 
解释:监听事件,网络流媒体的缓冲监听 

事件:setOnCompletionListener(MediaPlayer.OnCompletionListener listener) 
解释:监听事件,网络流媒体播放结束监听 

事件:setOnErrorListener(MediaPlayer.OnErrorListener listener) 
解释:监听事件,设置错误信息监听 

事件:setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener) 
解释:监听事件,视频尺寸监听 

方法:setScreenOnWhilePlaying(boolean screenOn) 
解释:无返回值,设置是否使用 SurfaceHolder 显示 

方法:setVolume(float leftVolume, float rightVolume) 
解释:无返回值,设置音量 

方法:start() 
解释:无返回值,开始播放 

方法:stop() 
解释:无返回值,停止播放
public class MediaPlayerDemo_Video extends Activity implements
OnBufferingUpdateListener, OnCompletionListener,
OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {

private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private String path;
private Bundle extras;
private static final String MEDIA = "media";
private static final int LOCAL_AUDIO = 1;
private static final int STREAM_AUDIO = 2;
private static final int RESOURCES_AUDIO = 3;
private static final int LOCAL_VIDEO = 4;
private static final int STREAM_VIDEO = 5;
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;

/**
*当活动第一次创建时调用。
*/
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.mediaplayer_2);
mPreview = (SurfaceView) findViewById(R.id.surface);
holder = mPreview.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
extras = getIntent().getExtras();

}

private void playVideo(Integer Media) {
doCleanUp();
try {

switch (Media) {
case LOCAL_VIDEO:
/*
* 将路径变量设置为本地媒体文件路径。
*/
path = "";
if (path == "") {
Toast.makeText( MediaPlayerDemo_Video.this,
"Please edit MediaPlayerDemo_Video Activity, "
+ "and set the path variable to your media file path."
+ " Your media file must be stored on sdcard.", Toast.LENGTH_LONG).show();

}
break;
case STREAM_VIDEO:
/*
* 将path变量设置为渐进式可流的mp4或3gpp格式的URL。应该使用Http协议。Mediaplayer只能播放“渐进式可流内容”,主要意思是:1。电影原子必须先于所有的媒体数据原子。2。这段视频必须合理交叉。
*
*/
path = "";
if (path == "") {

Toast
.makeText(
MediaPlayerDemo_Video.this,
"Please edit MediaPlayerDemo_Video Activity,"
+ " and set the path variable to your media file URL.",
Toast.LENGTH_LONG).show();

}

break;


}

// 创建一个新的媒体播放器并设置监听器
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(path);
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepare();
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);


} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}

public void onBufferingUpdate(MediaPlayer arg0, int percent) {
Log.d(TAG, "onBufferingUpdate percent:" + percent);

}

public void onCompletion(MediaPlayer arg0) {
Log.d(TAG, "onCompletion called");
}

public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
return;
}
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}

public void onPrepared(MediaPlayer mediaplayer) {
Log.d(TAG, "onPrepared called");
mIsVideoReadyToBePlayed = true;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}

public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
Log.d(TAG, "surfaceChanged called");

}

public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(TAG, "surfaceDestroyed called");
}


public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated called");
playVideo(extras.getInt(MEDIA));


}

@Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}

@Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}

private void releaseMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}

private void doCleanUp() {
mVideoWidth = 0;
mVideoHeight = 0;
mIsVideoReadyToBePlayed = false;
mIsVideoSizeKnown = false;
}

private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback");
holder.setFixedSize(mVideoWidth, mVideoHeight);
mMediaPlayer.start();
}
}