Android自定義視訊播放器(一)
一、引言
我們在開發Android多媒體應用時,有兩種方式來播放多媒體資源。第一種是使用隱式的Intent,來使用系統或者手機已經安裝的第三方播放器應用來播放音視訊,第二種是使用Android自帶的、我們自定義的播放器來播放,這種主要是採用Android提供的MediaPlayer和VideoView來播放多媒體檔案,下面會逐一講述。兩種方式的程式碼如下:
//隱式方式,使用第三方播放器 Intent intent = new Intent(); String url = "" intent.setDataAndType(Uri.parse(url),"video/*"); startActivity(intent); //呼叫自定義播放器 Intent intent = new Intent(context,VideoActivity.class); startActivity(intent);
對於自定義播放器,需要在VideoActivity的佈局檔案中,加入VideoView的定義,然後在VideoActivity中獲取,並使用:
setContentView(R.layout.activity_video); videoView = findViewById(R.id.mVideoView); //設定播放地址 videoView.setVideoPath(url); //設定準備好了的監聽 videoView.setOnPreparedListener(new MyPreparedListener()); videoView.setOnErrorListener(new MyErrorListener()); videoView.setOnCompletionListener(new MyCompletionListener()); //為VideoView新增控制面板,用於暫停和播放 videoView.setMediaController(new MediaController(this));
二、MediaPlay
1、MediaPlayer,它主要是和虛擬機器的底層進行打交道,包括下面要講的VideoView也是對它的封裝和呼叫。
2、MediaPlayer,封裝了很多播放音視訊的方法,如: start、pause、stop。(下圖部分方法)
3、MediaPlayer,可以播放本地和網路的音視訊,播放網路資源的時候,要聯網許可權。
4、MediaPlayer,可以支援的視訊格式:mp4、3gp、.m3u8(多用於直播)、直接用pc的.mp4檔案等
5、執行流程:
6、各狀態說明:
- 狀態1:Idel(空閒)狀態
當 mediaplayer建立或者執行reset()方法後處於這個狀態。 - 狀態2:Initialized(已初始化)狀態
當呼叫mediaplayer的setDataResource()方法給mediaplayer設定播放的資料來源後,mediaplayer會處於該狀態。 - 狀態3:Prepared(準備就續)狀態
設定完資料來源後,呼叫mediaplayer的prepare()方法,讓mediaplayer準備播放。值得一提的是,這裡除了prepare()方法,還有prepareAsnyc()方法,此方法是非同步方法,一般用於網路視訊的緩衝。當緩衝完畢後,就會觸發準備完畢的事件。我們要做的就是監聽該事件(OnPreparedListener),當緩衝完成時,執行相應的操作。在此狀態上,我們可以呼叫seekTo()方法定位視訊,此方法不改變mediaplayer的狀態;亦可呼叫stop()放棄視訊播放,使mediaplayer處於Stopped狀態。一般我們會在此狀態上呼叫start()方法開始播放視訊。 - 狀態4:Started(開始)狀態
當處於Prepared狀態、Paused狀態和PlayebackCompeleted狀態時,呼叫Started()方法即可進入該狀態。在該狀態中,mediaplayer開始播放視訊,可以通過seekTo()方法和start()方法改變視訊播放的進度,當Looping為真且播放完畢後,它會重新開始播放(即迴圈播放);否則播放完畢後,會觸發事件並呼叫OnCompletionaListener.OnCompletion()方法,進行特定操作,並進入PlaybackCompleted狀態。在此狀態中,亦可呼叫pause()方法或者stop()方法讓視訊暫停或停止,此時mediaplayer分別處於Stopped和Paused狀態。 - 狀態5:Stopped(停止)狀態
當 mediaplayer處於Prepared、Started、Paused、PlaybackCompleted狀態時,呼叫stop()方法即可進入本狀態。應特別注意的是,在本狀態中,若想重新開始播放,不能直接呼叫start()方法,必須呼叫prepare()方法或prepareAsync()方法重新讓mediaplayer處於Prepared狀態方可呼叫start()方法播放視訊。 - 狀態6:Paused(暫停)狀態
當mediaplayer處於Started狀態是,呼叫pause()方法即可進入本狀態。在本狀態裡,可直接呼叫start()方法使,mediaplayer回到Started狀態,亦可呼叫stop()方法停止視訊播放,讓播放器處於停止態。 - 狀態7:PlaybackCompleted(播放完成)狀態
當mediaplayer播放完成且Looping為假時即可進入本狀態。在本狀態可呼叫start()方法使mediaplayer回到Started狀態(注意此時是從頭開始播放);亦可呼叫stop()方法使mediaplayer處於停止態,結束播放。 - 狀態8:Error(錯誤)狀態
當mediaplayer出現錯誤時處於此狀態。
三、VideoView
1、VideoView,用於顯示視訊,繼承SurfaceView類,實現MediaPlayerControl介面。
2、封裝了MediaPlayer的start、pause、stop,本質上是對MediaPlayer的呼叫。(如:pause()方法是對MediaPlayer的呼叫)
3、SurfaceView,預設使用雙緩衝技術,它支援在子執行緒中繪製圖像,這樣就不會阻塞主執行緒了,所以它更適合於遊戲和視訊播放器的開發。
4、實現MediaPlayerControl介面,便於控制面板呼叫VideoView的方法
public interface MediaPlayerControl {
void start();
void pause();
int getDuration();
int getCurrentPosition();
void seekTo(int pos);
boolean isPlaying();
int getBufferPercentage();
boolean canPause();
boolean canSeekBackward();
boolean canSeekForward();
int getAudioSessionId();
}
videoview.setMediaController(new MediaController(this));
四、Activity的生命週期和橫豎屏切換的生命週期
Activity的生命週期流程圖
1、正常建立一個Activity執行的方法
onCreate-->onStart-->onResume
2、正常銷燬一個Activity執行的方法
onPause-->onStop->onDestroy
3、A頁面跳轉到B頁面,點選返回,這個過程中的生命週期
(1)、B頁面完全覆蓋A頁面的情況
A跳轉B頁面的生命週期方法執行順序:
onPause(A)->onCreate(B)--->onStart(B)--->onResume(B)--->onStop(A)
B頁面點選後返回生命週期執行順序:
onPause(B)-->onRestart(A)-->onStart(A)-->onResume(A)->onStop(B)-->onDestroy(B)
(2)、B頁面不完全覆蓋A頁面的請求
A跳轉B頁面的生命週期方法執行順序
onPause(A)-->onCreate(B)-->onStart(B)-->onResume(B)
B頁面點選後返回生命週期執行順序
onPause(B)-->onResume(A)-->->onStop(B)-->onDestroy(B)
4、Activity橫豎屏切換的生命週期
(1)、預設情況,螢幕橫豎屏切換會讓Activity的生命週期重新執行:
onPause-->onStop-->onDestroy-->onCreate-->onStart-->onResume
(2)、在Manifest檔案中,相應的Activity配置如下,不會讓生命週期重新執行:
onPause-->onStop-->onDestroy
<activity android:name=".activity.VideoActivity"
android:configChanges="keyboardHidden|screenSize|orientation"
/>
五、總結
1、其實想用VideoView播放視訊很簡單,只需要在佈局檔案裡,定義一個VideoView,然後在Activity中獲取到,設定播放地址,併為VideoView繫結幾個監聽器,就可以進行對視訊的播放了。
2、對於播放視訊的地址,可以分為:
- 本地資源(我理解為只屬於這個應用的)
- Internal URIs, 比如可以通過 Content Resolver 獲得的
- External URLs (流媒體)
3、下圖為使用VideoView自帶的控制面板播放網路視訊的示意圖(自帶的控制面板看著有點醜哦):