一、簡介
作為Android開發,我們不可避免的會接觸到視頻播放,VideoView做為最簡單的播放器,我們是不應該不會的。
下面簡單介紹一下VideoView:
- VideoView是使用MediaPlayer來對視頻文件進行控制的。
- VideoView只支持mp4、avi、3gp格式的視頻,支持格式相對單一,VideoView支持的格式可以參考MediaPlayer。
- VideoView可以播放網絡視頻,支持的網絡視頻的協議為:Http協議和RTSP協議兩種。
二、VideoView常用方法
Android VideoView類為我們提供了十分方便的視頻播放API,其主要方法如下:
- setVideoPath:設置要播放的視頻文件的位置
- start:開始或繼續播放視頻
- pause:暫停播放視頻
- resume:將視頻從頭開始播放
- seekTo:從指定的位置開始播放視頻
- isPlaying:判斷當前是否正在播放視頻
- getCurrentPosition:獲取當前播放的位置
- getDuration:獲取載入的視頻文件的時長
- setVideoPath(String path):以文件路徑的方式設置VideoView播放的視頻源
- setVideoURI(Uri uri):以Uri的方式設置視頻源,可以是網絡Uri或本地Uri
- setMediaController(MediaController controller):設置MediaController控制器
- setOnCompletionListener(MediaPlayer.onCompletionListener l):監聽播放完成的事件
- setOnErrorListener(MediaPlayer.OnErrorListener l):監聽播放發生錯誤時候的事件
- setOnPreparedListener(MediaPlayer.OnPreparedListener l):監聽視頻裝載完成的事件
除了簡單的操作和豐富的API以外,我們在裝載視頻時,無需進行編碼,播放完成后也無需手動回收資源。
除了播放視頻,Media Controller類則為我們提供了一個懸浮的操作欄,包含了播放,暫停,快進,快退,上一個,下一個等功能鍵。甚至連拖動進度條至某處播放都已經實現。在使用前VideoView和MediController需要相互指定控件。其內置方法有如下:
boolean isShowing:當前懸浮控制欄是否顯示
setMediaPlayer(MediaController.MediaPlayerControl player):設置控制的組件
setPrevNextListeners(View.OnClickListener next,View.OnClickListener prev):設置上一個視頻、下一個視頻的切換事件。
默認情況下,Media Controller懸浮顯示3s后隱藏,觸摸響應的VideoView呼出。默認上一個,下一個按鈕隱藏。
三、使用VideoView實現視頻播放
下面我們將展示如何使用VideoView播放香港衛視的視頻流:
1. 聲明權限
需要在AndroidManifest.xml添加兩條權限。
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
兩條權限分別為:網絡訪問權限、訪問文件系統的權限。
2. 編寫VideoView布局
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <VideoView android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </android.support.constraint.ConstraintLayout>
3. 編寫播放視頻代碼
VideoView videoView = findViewById(R.id.video_view); videoView.setVideoPath("http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8"); // 香港衛視地址 videoView.start(); MediaController mediaController = new MediaController(this); videoView.setMediaController(mediaController); mediaController.setMediaPlayer(videoView);
4. 效果圖
完成代碼編寫的工作后啟動App應該就能夠如上圖的香港衛視的視頻內容啦。是不是感覺很簡單啊,那是因為VideoView封裝了MediaPlayer和SurfaceView,所有的生命周期都包裝好了,所以使用的時候當然就簡單啦。下面我們就解析一下VideoView了解其背后的事情。
四、VideoView 播放狀態說明
下面的代碼是VideoView聲明的播放器聲明的狀態:
// all possible internal states private static final int STATE_ERROR = -1; private static final int STATE_IDLE = 0; private static final int STATE_PREPARING = 1; private static final int STATE_PREPARED = 2; private static final int STATE_PLAYING = 3; private static final int STATE_PAUSED = 4; private static final int STATE_PLAYBACK_COMPLETED = 5;
為什么會聲明這些狀態,這就不得不提到MediaPlayer的生命周期了,看下圖,應該就稍微理解了吧:
在這里我們先不具體針對這個圖講MediaPlayer的生命周期的內容。只是為了證明VideoView的狀態的生命是有依據的。
private int mCurrentState = STATE_IDLE; private int mTargetState = STATE_IDLE;
上面的代碼聲明了兩個狀態變量,分別是當前的狀態和目標狀態。通過這兩個變量結合上面提到的常量,我們可以很清楚的知道VideoView類就是圍繞這這兩個狀態來進行相應的操作的。而我們處理一些回調也是基於這些狀態之間的變化設計的,如:
- OnCompletionListener -- STATE_PLAYBACK_COMPLETED
- OnPreparedListener -- STATE_PREPARED
- OnErrorListener -- STATE_ERROR
五、使用VideoView 可能遇到的問題及解決方案
1. 視頻播放時會有短暫的黑屏時間:
產生原因:
視頻文件加載到內存中是需要時間,這個時間可能導入VideoView全黑。
解決方法:
(1):給VideoView添加MediaPlayer.OnPreparedListener 監聽事件,在其onPrepared(MediaPlayer mp) 方法回調中播放視頻這個時候視頻已經完成了加載。
(2):在VideoView執行start() 方法時視頻的預覽圖不是立即消失而是延遲幾百毫秒之后消失,這是視頻已經加載完成,當然體驗上有些不好。
2. 跳轉到其他界面回來后視頻播放區域黑屏:
產生原因:
VideoView被回收掉,而自己沒做VideoView的狀態保存處理
解決方法:
在VideoView所在的Activity或者Fragment的生命周期中處理VideoView視頻播放和暫停。(查看VideoView的生命周期相關的方法)