最近为了比较全面的了解一下Android的知识体系结构,买了一个Android4 高级编程研读一下,在学习第十五章音频、视频以及摄像头的使用的时候,书本上的MediaPlayer和MediaController联合使用的例子没有调通。搜索良久找到答案在此记录一下。
使用的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- Listing 15-3: Sample layout using a Surface View -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
<SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="30" />
<LinearLayout android:id="@+id/ll" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
相关Java代码如下:
package com.paad.mediaplayer;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.MediaController;
import constant.Constants;
public class AudioPlayer extends Activity implements OnPreparedListener, MediaController.MediaPlayerControl {
private static final String TAG = "AudioPlayer";
private MediaPlayer mediaPlayer;
private MediaController mediaController;
private Handler handler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.surfaceviewvideoviewer);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
try {
//TODO 这里填写你的本地视频文件路径
mediaPlayer.setDataSource(Constants.PATH_VEDIO);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e(TAG, "Could not open file xxx for playback.", e);
}
final SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.setKeepScreenOn(true);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mediaPlayer.release();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mediaPlayer.setDisplay(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
});
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.setFixedSize(400, 300);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// the MediaController will hide after 3 seconds - tap the screen to
// make it appear again
mediaController.show();
return false;
}
// --MediaPlayerControl
// methods----------------------------------------------------
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
// --------------------------------------------------------------------------------
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG, "onPrepared");
mediaController = new MediaController(this);
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(findViewById(R.id.ll));
mediaController.setEnabled(true);
handler.post(new Runnable() {
public void run() {
mediaController.show();
}
});
}
@Override
public int getAudioSessionId() {
// TODO Auto-generated method stub
return 0;
}
}
代码罗列在这里了,我还想啰嗦几句:
1.OnPreparedListener不是必须的,主要是为mediaController.show();服务的,将onPrepared中的代码块移动到onCreate里面也是ok的,但是,要做稍微的调整,将handler.post修改为了handler.postDelayed,设置一个延迟执行的时间(让mediaPlayer完成播放前的初始化)也是ok的。
2.至于为什么在代码初始化后,调用mediaController.show()必须放到handler.post中,我猜想是因为mediaController的初始化也是通过handler机制进行更新的,通过handler是通过队列机制对消息进行处理了,这样就保证了mediaController的初始化和mediaController.show的顺序。
3.至于为什么将mediaPlayer.setDisplay(holder);设置放到surfaceCreated方法中,SurfaceView的创建是异步的,实例化后,并没有完成创建。
这个就要简单的多了,不需要SurfaceView来展示视频了,下面贴一下代码:
package com.paad.mediaplayer;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.MediaController;
import constant.Constants;
public class AudioPlayer extends Activity implements OnPreparedListener, MediaController.MediaPlayerControl {
private static final String TAG = "AudioPlayer";
private MediaPlayer mediaPlayer;
private MediaController mediaController;
private Handler handler = new Handler();
private LinearLayout mControllLayout;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mControllLayout=new LinearLayout(this);
setContentView(mControllLayout);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
try {
//TODO 这里写你的音频路径
mediaPlayer.setDataSource(Constants.PATH_AUDIO);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
Log.e(TAG, "Could not open file xxx for playback.", e);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// the MediaController will hide after 3 seconds - tap the screen to
// make it appear again
mediaController.show();
return false;
}
// --MediaPlayerControl
// methods----------------------------------------------------
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG, "onPrepared");
mediaController = new MediaController(this);
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(mControllLayout);
mediaController.setEnabled(true);
handler.post(new Runnable() {
public void run() {
mediaController.show();
}
});
}
@Override
public int getAudioSessionId() {
// TODO Auto-generated method stub
return 0;
}
}