前言 之前有講過如何使用SurfaceView配合MediaPlayer播放視訊,其實Android還為開發人員提供了另外一種更簡單的播放視訊媒體的方式,那就是VideoView,本篇部落格就來講講VideoView如何播放視訊,最後将以一個簡單的Demo示範。 本篇部落格的主要内容如下: VideoView VideoView簡單的Demo MediaController MediaController簡單的Demo VideoView VideoView,用于播放一段視訊媒體,它繼承了SurfaceView,位于"android.widget.VideoView",是一個視訊控件。 既然是播放一段視訊,那麼不可避免的要涉及到一些開始、暫停、停止等操作,VideoView也為開發人員提供了對應的方法,這裡簡單介紹一些常用的: int getCurrentPosition():擷取目前播放的位置。 int getDuration():擷取目前播放視訊的總長度。 isPlaying():目前VideoView是否在播放視訊。 void pause():暫停 void seekTo(int msec):從第幾毫秒開始播放。 void resume():重新播放。 void setVideoPath(String path):以檔案路徑的方式設定VideoView播放的視訊源。 void setVideoURI(Uri uri):以Uri的方式設定VideoView播放的視訊源,可以是網絡Uri或本地Uri。 void start():開始播放。 void stopPlayback():停止播放。 setMediaController(MediaController controller):設定MediaController控制器。 setOnCompletionListener(MediaPlayer.onCompletionListener l):監聽播放完成的事件。 setOnErrorListener(MediaPlayer.OnErrorListener l):監聽播放發生錯誤時候的事件。 setOnPreparedListener(MediaPlayer.OnPreparedListener l)::監聽視訊裝載完成的事件。 上面的一些方法通過方法名就可以了解用途。和MediaPlayer配合SurfaceView播放視訊不同,VideoView播放之前無需編碼裝載視訊,它會在start()開始播放的時候自動裝載視訊。并且VideoView在使用完之後,無需編碼回收資源。 VideoView簡單的Demo VideoView其實沒有什麼難點,通過它自帶的API方法,即可完成一段視訊的播放,無非就是注意它方法的調用時機即可。下面通過一個簡單的Demo,示範VideoView如何播放一段SD卡上的視訊檔案。在Demo中提供了四個Button,分别表示播放、暫停、重播、停止,并配合進度條顯示。代碼注釋比較完整,細節部分這裡不再累述。 布局代碼:activity_videoview.xml View Code 實作代碼:VideoViewActivity.java
package cn.bgxt.videoviewdemo;
import java.io.File;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.Toast;
import android.widget.VideoView;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class VideoViewActivity extends Activity {
private final String TAG = "main";
private EditText et_path;
private Button btn_play, btn_pause, btn_replay, btn_stop;
private SeekBar seekBar;
private VideoView vv_video;
private boolean isPlaying;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videoview);
seekBar = (SeekBar) findViewById(R.id.seekBar);
et_path = (EditText) findViewById(R.id.et_path);
vv_video = (VideoView) findViewById(R.id.vv_videoview);
btn_play = (Button) findViewById(R.id.btn_play);
btn_pause = (Button) findViewById(R.id.btn_pause);
btn_replay = (Button) findViewById(R.id.btn_replay);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_play.setOnClickListener(click);
btn_pause.setOnClickListener(click);
btn_replay.setOnClickListener(click);
btn_stop.setOnClickListener(click);
// 為進度條添加進度更改事件
seekBar.setOnSeekBarChangeListener(change);
}
private OnSeekBarChangeListener change = new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 當進度條停止修改的時候觸發
// 取得目前進度條的刻度
int progress = seekBar.getProgress();
if (vv_video != null && vv_video.isPlaying()) {
// 設定目前播放的位置
vv_video.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
};
private View.OnClickListener click = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:
play(0);
break;
case R.id.btn_pause:
pause();
break;
case R.id.btn_replay:
replay();
break;
case R.id.btn_stop:
stop();
break;
default:
break;
}
}
};
protected void play(int msec) {
Log.i(TAG, " 擷取視訊檔案位址");
String path = et_path.getText().toString().trim();
File file = new File(path);
if (!file.exists()) {
Toast.makeText(this, "視訊檔案路徑錯誤", 0).show();
return;
}
Log.i(TAG, "指定視訊源路徑");
vv_video.setVideoPath(file.getAbsolutePath());
Log.i(TAG, "開始播放");
vv_video.start();
// 按照初始位置播放
vv_video.seekTo(msec);
// 設定進度條的最大進度為視訊流的最大播放時長
seekBar.setMax(vv_video.getDuration());
// 開始線程,更新進度條的刻度
new Thread() {
@Override
public void run() {
try {
isPlaying = true;
while (isPlaying) {
// 如果正在播放,沒0.5.毫秒更新一次進度條
int current = vv_video.getCurrentPosition();
seekBar.setProgress(current);
sleep(500);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
// 播放之後設定播放按鈕不可用
btn_play.setEnabled(false);
vv_video.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// 在播放完畢被回調
btn_play.setEnabled(true);
}
});
vv_video.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// 發生錯誤重新播放
play(0);
isPlaying = false;
return false;
}
});
}
/**
* 重新開始播放
*/
protected void replay() {
if (vv_video != null && vv_video.isPlaying()) {
vv_video.seekTo(0);
Toast.makeText(this, "重新播放", 0).show();
btn_pause.setText("暫停");
return;
}
isPlaying = false;
play(0);
}
/**
* 暫停或繼續
*/
protected void pause() {
if (btn_pause.getText().toString().trim().equals("繼續")) {
btn_pause.setText("暫停");
vv_video.start();
Toast.makeText(this, "繼續播放", 0).show();
return;
}
if (vv_video != null && vv_video.isPlaying()) {
vv_video.pause();
btn_pause.setText("繼續");
Toast.makeText(this, "暫停播放", 0).show();
}
}
/*
* 停止播放
*/
protected void stop() {
if (vv_video != null && vv_video.isPlaying()) {
vv_video.stopPlayback();
btn_play.setEnabled(true);
isPlaying = false;
}
}
}
效果展示:
MediaController 提到VideoView不得不再說一些MediaController。雖然VideoView為我們提供了友善的API用于播放、暫停、停止等操作,但是還是需要我們編碼完成,但是如果使用了MediaController的話,那麼這些操作都可以省去。 MediaController可以用于配合VideoView播放一段視訊,它為VideoView提供一個懸浮的操作欄,在操作欄中可以對VideoView播放的視訊進行控制,預設情況下,會懸浮顯示三秒。它通過MediaController.setMediaPlayer()方法進行指定需要控制的VideoView,但是僅僅這樣是不夠的,MediaController的控制需要類似于雙向控制,MediaController指定控制的VideoView,VideoView還需要指定那個MediaController來控制它,這需要使用VideoView.setMediaController()方法。 下面介紹一下MediaController的一些常用方法; boolean isShowing():目前懸浮控制欄是否顯示。 void setMediaPlayer(MediaController.MediaPlayerControl player):設定控制的 元件。 void setPrevNextListeners(View.OnClickListener next,View.OnClickListener prev):設定上一個視訊、下一個視訊的切換事件。 通過上面的方法可以看出setMediaPlayer()并非指定的是一個VideoView,而是一個MediaPlayerControl接口,MediaPlayerControl接口内部定義了一些播放相關的播放、暫停、停止等操作,而VideoView實作了MediaPlayerControl。 預設情況下,如果不通過setPrevNextListeners()設定切換視訊的監聽器,MediaController是不會顯示這兩個按鈕的。 MediaController簡單的Demo 上面已經講過MediaController的一些内容,下面通過一個簡單的Demo來示範一下MediaController控制VideoView播放視訊。 布局代碼:activity_controller.xml View Code 實作代碼:ControllerActivity.java
package cn.bgxt.videoviewdemo;
import java.io.File;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.MediaController;
import android.widget.Toast;
import android.widget.VideoView;
public class ControllerActivity extends Activity {
private VideoView vv_video;
private MediaController mController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controller);
vv_video=(VideoView) findViewById(R.id.vv_video);
// 執行個體化MediaController
mController=new MediaController(this);
File file=new File("/sdcard/ykzzldx.mp4");
if(file.exists()){
// 設定播放視訊源的路徑
vv_video.setVideoPath(file.getAbsolutePath());
// 為VideoView指定MediaController
vv_video.setMediaController(mController);
// 為MediaController指定控制的VideoView
mController.setMediaPlayer(vv_video);
// 增加監聽上一個和下一個的切換事件,預設這兩個按鈕是不顯示的
mController.setPrevNextListeners(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ControllerActivity.this, "下一個",0).show();
}
}, new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ControllerActivity.this, "上一個",0).show();
}
});
}
}
}
從上面展示的效果可以看出,MediaController不光為我們增加了控制欄來控制播放、暫停、快進、快退、切換上一視訊、切換下一視訊,還增加了進度條顯示。 原文位址: http://www.2cto.com/kf/201312/261877.html