有趣的安卓視訊播放器(VideoView)
VideoView是安卓自帶的視訊播放器類,該類整合有顯示和控制兩大部分,在佈局檔案中新增VideoView然後在java檔案中簡單的呼叫控制命令,即可實現本地或者網路視訊的播放。本章實現視訊的居中播放、網路視訊播放、本地視訊播放、視訊卡頓監聽、網路連線錯誤監聽、視訊外自定義視訊控制元件、視訊內自定義視訊控制元件等。
支援的格式:flv、3gp、mp4
類的一些重要方法
void start(); //開始播放
void pause(); //暫停
void resume(); //重新播放,使用時需要在本句後加上開始播放
void seekTo(int msec); //從第幾毫秒開始播放
void stopPlayback(); //停止播放並釋放資源
int getCurrentPosition(); //獲取當前播放的位置。
int getDuration(); //獲取當前播放視訊的總長度。
void setVideoPath(String path); //以檔案路徑的方式設定VideoView播放的視訊源。
void setVideoURI(Uri uri); //以Uri的方式設定VideoView播放的視訊源,可以是網路Uri或本地Uri
void isPlaying(); //當前VideoView是否在播放視訊
setMediaController(MediaController controller); //設定MediaController控制器
setOnCompletionListener(MediaPlayer.onCompletionListener l); //監聽播放完成的事件
setOnErrorListener(MediaPlayer.OnErrorListener l); //監聽播放發生錯誤時候的事件
setOnPreparedListener(MediaPlayer.OnPreparedListener l); //監聽視訊裝載完成的事件
setOnInfoListener(new MediaPlayer.OnInfoListener(){}); //視訊卡頓監聽
實現簡單的視訊播放
佈局檔案:
實現視訊播放重要在於 VideoView標籤,如果讓該標籤的父級標籤為FramLayout,設定相應屬性就可以實現視訊居中播放和預設的播放控制元件 MediaController 在視訊內顯示效果,還可以在VidoView標籤上層加入TextView標籤,實現視訊播放的一些狀態顯示,如播放卡頓、切換播放、播放失敗等的提示資訊顯示。另外可加入ImageView標籤,即可顯示圖片或gif圖,更具人性化。
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3xmlns:tools="http://schemas.android.com/tools" 4android:layout_width="match_parent" 5android:layout_height="match_parent" 6android:paddingBottom="0dp" 7android:paddingLeft="0dp" 8android:paddingRight="0dp" 9android:orientation="vertical" 10android:paddingTop="0dp" 11tools:context="com.example.videodong.MainActivity"> 12 13<TextView 14android:layout_width="wrap_content" 15android:layout_height="wrap_content" 16android:text="視訊播放器:\n" 17android:textSize="15dp" 18android:id="@+id/textView" /> 19<FrameLayout 20android:layout_width="match_parent" 21android:background="@color/colorBlack" 22android:layout_height="300dp"> 23<VideoView 24android:layout_width="match_parent" 25android:layout_gravity="center" 26android:layout_height="300dp" 27android:id="@+id/videoView" 28/> 29 30<TextView 31android:layout_width="wrap_content" 32android:layout_height="wrap_content" 33android:textSize="15dp" 34android:text="點選播放" 35android:textColor="@color/colorWhite" 36android:id="@+id/vv_text" 37android:layout_gravity="center" /> 38</FrameLayout> 39 40<ProgressBar 41android:id="@+id/vv_bar" 42style="?android:attr/progressBarStyleHorizontal" 43android:layout_width="match_parent" 44android:layout_height="wrap_content"/> 45 46<TextView 47android:layout_width="wrap_content" 48android:text="時間軸為:0.00/000" 49android:id="@+id/vv_starttime" 50android:layout_height="wrap_content" /> 51 52 53<LinearLayout 54android:layout_width="match_parent" 55android:orientation="horizontal" 56android:layout_gravity="center" 57android:layout_height="wrap_content"> 58<TextView 59android:layout_width="wrap_content" 60android:layout_weight="1" 61android:layout_height="wrap_content" /> 62<Button 63android:layout_width="wrap_content" 64android:text="開始" 65android:id="@+id/vv_start" 66android:layout_height="wrap_content" /> 67<Button 68android:layout_width="wrap_content" 69android:text="暫停" 70android:id="@+id/vv_pause" 71android:layout_height="wrap_content" /> 72<Button 73android:layout_width="wrap_content" 74android:text="重播" 75android:id="@+id/vv_restart" 76android:layout_height="wrap_content" /> 77<Button 78android:layout_width="wrap_content" 79android:text="下一個" 80android:id="@+id/vv_next" 81android:layout_height="wrap_content" /> 82 83</LinearLayout> 84<TextView 85android:layout_width="wrap_content" 86android:id="@+id/vv_state" 87android:layout_height="wrap_content" /> 88 </LinearLayout> View Code
需要新增的許可權:
因為視訊來源可以是網路或者本地,所以需要動態申請網路訪問許可權和本地檔案讀寫許可權,檔案讀寫許可權一般還需要手動獲取
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
尋找到VideoView控制元件:
vv=(VideoView)findViewById(R.id.videoView);
視訊預裝完成監聽:
1 //視訊準備完成時進入 2 vv.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 3@Override 4public void onPrepared(MediaPlayer mp) { 5//設定螢幕提示資訊為空 6vv_text.setText(""); 7} 8 });
視訊播放完成監聽:
1 vv.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 2@Override 3public void onCompletion(MediaPlayer mp) { 4String strres="播放完成"; 5//判斷視訊的總長度與當前長度是否在誤差區間內 6if(Math.abs(vv.getDuration()-vv.getCurrentPosition())>1000){ 7 8strres="播放錯誤,可能無網路連線"; 9 10} 11//設定螢幕提示資訊 12vv_text.setText(strres); 13 14} 15 });
視訊播放錯誤監聽:
1 vv.setOnErrorListener(new MediaPlayer.OnErrorListener() { 2@Override 3public boolean onError(MediaPlayer mp, int what, int extra) 4{ 5//設定螢幕顯示資訊 6vv_text.setText("視訊未知錯誤"); 7 8return false; 9} 10});
視訊卡頓和停止卡頓監聽:
1 vv.setOnInfoListener(new MediaPlayer.OnInfoListener(){ 2@Override 3public boolean onInfo(MediaPlayer mp, int what, int extra){ 4 5switch(what){ 6case MediaPlayer.MEDIA_INFO_BUFFERING_START: 7//設定螢幕顯示資訊,開始卡頓 8vv_text.setText("視訊卡頓,載入中....."); 9break ; 10case MediaPlayer.MEDIA_INFO_BUFFERING_END: 11//設定螢幕顯示資訊,卡頓結束 12vv_text.setText(""); 13break ; 14} 15return true; 16} 17 }) ;
設定播放資源:
1 //本地檔案 2 vv.setVideoPath(Environment.getExternalStorageDirectory()+"/dongxiaodong/kk1.mp4"); 3 4 //URL形式,支援本地URL和網路URL 5 //vv.setVideoURI(Uri.parse("https://www.bilibili.com/video/xxxxx")); 6 7 //設定自帶的播放控制元件 8 //vv.setMediaController(new MediaController(this));
播放開始按鈕監聽:
1 //開始播放視訊按鈕 2 vv_start.setOnClickListener(new View.OnClickListener() { 3@Override 4public void onClick(View v) { 5 6//設定螢幕顯示資訊 7vv_text.setText(""); 8 9//開始播放 10vv.start(); 11 12} 13 });
播放暫停按鈕監聽:
1 //暫停播放視訊按鈕 2 vv_pause.setOnClickListener(new View.OnClickListener() { 3@Override 4public void onClick(View v) { 5 6//設定螢幕顯示資訊 7vv_text.setText("視訊暫停中"); 8 9//暫停視訊播放 10vv.pause(); 11 12} 13 });
重新播放按鈕監聽:
1 //重新播放視訊 2 vv_restart.setOnClickListener(new View.OnClickListener() { 3@Override 4public void onClick(View v) { 5//設定螢幕顯示資訊 6vv_text.setText("正在重新播放中,請稍等"); 7 8//設定時間軸顯示為0 9vv_starttime.setText("時間軸為:0.00/0.00"); 10 11//設定進度條顯示為0 12vv_bar.setProgress(0); 13 14//重新播放視訊 15vv.resume(); 16vv.start(); 17 18} 19 });
播放下一個視訊監聽:
1 vv_next.setOnClickListener(new View.OnClickListener() { 2@Override 3public void onClick(View v) { 4//設定螢幕顯示資訊 5vv_text.setText("正在切換,請稍等"); 6 7//設定時間軸為0 8vv_starttime.setText("時間軸為:0.00/0.00"); 9 10//設定進度條為0 11vv_bar.setProgress(0); 12 13//停止播放 14vv.pause();//暫停 15vv.stopPlayback();//停止播放並釋放資源 16 17//得到下一個視訊的資源 18if(nextbool){ 19nextbool=false; 20//網路資源,該url已經過期 21vv.setVideoURI(Uri.parse("http://193.112.87.88/video/xx.flv")); 22} else { 23nextbool=true; 24//本地資源 25vv.setVideoPath(Environment.getExternalStorageDirectory()+"/dongxiaodong/kk1.mp4"); 26} 27 28//開始播放下一個 29vv.start(); 30 31} 32 });
時間軸時間顯示和進度條更新實現:
時間軸時間顯示計算將在後文給出解釋,另外 %02d 可以實現自動補零效果,runOnUiThread可以在普通執行緒中進入UI執行緒,可以實現UI的一系列操作。
1 new Thread(new Runnable() { 2@Override 3public void run() { 4while (true){ 5//延時1秒 6try { 7Thread.sleep(1); 8} catch (InterruptedException e) { 9e.printStackTrace(); 10} 11 12//進入主執行緒更新UI 13runOnUiThread(new Runnable() { 14@Override 15public void run() { 16if(vv.isPlaying()) { 17 18//獲取到視訊播放進度 19int maxx=vv.getDuration(); 20int progress=vv.getCurrentPosition(); 21 22//設定進度條資訊 23vv_bar.setMax(maxx); 24vv_bar.setProgress(progress); 25 26//得到時間軸字串 27String strtime=String.format("時間軸為:%02d:%02d/%02d:%02d", (progress % 3600000) / 60000,(progress % 60000 ) / 1000, (maxx % 3600000) / 60000,(maxx % 60000 ) / 1000); 28//顯示時間軸資訊 29vv_starttime.setText(strtime); 30 31} 32} 33}); 34} 35 36} 37}).start(); View Code
視訊播放進階
利用FrameLayout的層疊效果,實現視訊控制元件面板在視訊層之上顯示,利用視訊控制元件的點選事件,實現視訊點選監聽然後改變視訊控制面板的隱藏和顯示。其他的視訊播放控制程式碼基本以上相似
佈局檔案改變:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3xmlns:tools="http://schemas.android.com/tools" 4android:layout_width="match_parent" 5android:layout_height="match_parent" 6android:paddingBottom="0dp" 7android:paddingLeft="0dp" 8android:paddingRight="0dp" 9android:orientation="vertical" 10android:paddingTop="0dp" 11tools:context="com.example.videodong.MainActivity"> 12 13<TextView 14android:layout_width="wrap_content" 15android:layout_height="wrap_content" 16android:text="視訊播放器:\n" 17android:textSize="15dp" 18android:id="@+id/textView" /> 19<FrameLayout 20android:layout_width="match_parent" 21android:background="@color/colorBlack" 22android:layout_height="230dp"> 23<VideoView 24android:layout_width="match_parent" 25android:layout_gravity="center" 26android:layout_height="230dp" 27android:id="@+id/videoView" 28/> 29<FrameLayout 30android:layout_width="match_parent" 31android:layout_gravity="bottom" 32android:id="@+id/vv_framel" 33android:layout_height="wrap_content"> 34<ImageView 35android:layout_width="match_parent" 36android:background="@color/colorWhite" 37android:alpha="0.5" 38android:layout_height="match_parent" /> 39<LinearLayout 40android:layout_width="match_parent" 41android:orientation="vertical" 42 43android:layout_height="wrap_content"> 44<ProgressBar 45android:id="@+id/vv_bar" 46style="?android:attr/progressBarStyleHorizontal" 47android:layout_width="match_parent" 48android:layout_height="wrap_content"/> 49<LinearLayout 50android:layout_width="match_parent" 51android:orientation="horizontal" 52android:layout_gravity="center" 53android:layout_height="wrap_content"> 54<TextView 55android:layout_width="wrap_content" 56android:text="時間軸為:0.00/000" 57android:id="@+id/vv_starttime" 58android:layout_weight="1" 59android:layout_height="wrap_content" /> 60<Button 61android:layout_width="wrap_content" 62android:text="開始" 63style="?android:attr/buttonStyleSmall" 64android:id="@+id/vv_start" 65android:layout_height="wrap_content" /> 66<Button 67android:layout_width="wrap_content" 68android:text="暫停" 69android:id="@+id/vv_pause" 70style="?android:attr/buttonStyleSmall" 71android:layout_height="wrap_content" /> 72<Button 73android:layout_width="wrap_content" 74android:text="重播" 75style="?android:attr/buttonStyleSmall" 76android:id="@+id/vv_restart" 77android:layout_height="wrap_content" /> 78<Button 79android:layout_width="wrap_content" 80android:text="下一個" 81style="?android:attr/buttonStyleSmall" 82android:id="@+id/vv_next" 83android:layout_height="wrap_content" /> 84 85</LinearLayout> 86</LinearLayout> 87</FrameLayout> 88 89<TextView 90android:layout_width="wrap_content" 91android:layout_height="wrap_content" 92android:textSize="15dp" 93android:text="點選播放" 94android:textColor="@color/colorWhite" 95android:id="@+id/vv_text" 96android:layout_gravity="center" /> 97</FrameLayout> 98 </LinearLayout> View Code
尋找播放控制元件標籤:
vv_framel=(FrameLayout)findViewById(R.id.vv_framel);
設定視訊播放控制元件點選事件監聽:
1 vv.setOnClickListener(new View.OnClickListener() { 2@Override 3public void onClick(View v) { 4//判斷是否是顯示 5if(vv_framel.getVisibility()==View.VISIBLE) 6 7//隱藏視訊播放控制元件 8vv_framel.setVisibility(View.INVISIBLE); 9 10else 11 12//顯示視訊播放控制元件 13vv_framel.setVisibility(View.VISIBLE); 14 15} 16 });
視訊播放時間軸時間計算:
如果只知道毫秒數,如何轉換為對應的時、分、秒,因為1秒為1000毫秒,1分鐘為60秒,1小時為60分,所以如果求秒則需要去掉分鐘的值,如果求分鐘則需要去掉小時的值。
得到秒:【(t % (60*1000) ) / 1000】
得到分:【(t % (60*60*1000)) / (60*1000)】
得到時:【(t / (60*60*1000))】
原始碼資源下載: 點我下載
參考:
https://www.jianshu.com/p/0c3ef72c20d1?from=timeline&isappinstalled=0
https://www.cnblogs.com/tangs/articles/5463347.html
https://blog.csdn.net/qq_30983519/article/details/54407122
https://blog.csdn.net/qq_29272491/article/details/80475788