代碼已經托管到碼云,有興趣的小伙伴可以下載看看
https://git.oschina.net/joy_yuan/MobilePlayer
一、設置視頻緩沖進度
顯示視頻播放進度的效果圖如下:灰色的是緩沖的進度。
原理:只有播放網絡視頻時,才有緩沖這個說法,所以要先判斷視頻資源是否為網絡資源
/***?判斷是否是網絡的資源*?@param?uri*?@return*/
public?boolean?isNetUri(String?uri)?{boolean?reault?=?false;if?(uri?!=?null)?{if?(uri.toLowerCase().startsWith("http")?||?uri.toLowerCase().startsWith("rtsp")?||?uri.toLowerCase().startsWith("mms"))?{reault?=?true;}}return?reault;
}
因此在前面,不管是單個的URI還是通過list傳來的mediaitem數組,都要根據地址來去判斷,然后在handler里去設置進度條。
????進度條很簡單,只需要設置seekbarVideo.setSecondaryProgress(int progress);即可達到設置進度。那么這個緩沖值怎么獲取的呢,這個是一個統一的寫法,沒有什么原因,如下代碼:
????
//網絡資源緩沖
if?(isNetUri){//只有網絡資源有緩沖int?bufferPercentage?=?videoview.getBufferPercentage();??//0~100int?totalbuffer?=?bufferPercentage?*?seekbarVideo.getMax();int?secordProgress=totalbuffer/100;seekbarVideo.setSecondaryProgress(secordProgress);
}else{//本地進度條沒有緩沖,即第二條進度條為灰色seekbarVideo.setSecondaryProgress(0);
}
二、使播放本地視頻時,可以跳出來選擇自定義播放器的方法。當我們手機里裝了多個播放器后,如果要播放本地視頻,系統會跳出來一個選擇框,讓用戶選擇播放哪個視頻這里用到里隱式意圖,只要給SystemVideoPlayer這個activity在AndroidManifext.xml里配置隱式意圖即可:<activityandroid:name=".activity.SystemVideoPlayer"android:configChanges="keyboardHidden|screenSize|orientation"android:screenOrientation="landscape"><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="rtsp"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><data?android:mimeType="video/*"?/><data?android:mimeType="application/sdp"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="http"?/><data?android:mimeType="video/mp4"?/><data?android:mimeType="video/3gp"?/><data?android:mimeType="video/3gpp"?/><data?android:mimeType="video/3gpp2"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.LAUNCHER"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><dataandroid:mimeType="video/*"android:scheme="http"?/><dataandroid:mimeType="video/*"android:scheme="rtsp"?/><dataandroid:mimeType="video/*"android:scheme="rtmp"?/><dataandroid:mimeType="video/*"android:scheme="udp"?/><dataandroid:mimeType="video/*"android:scheme="tcp"?/><dataandroid:mimeType="video/*"android:scheme="file"?/><dataandroid:mimeType="video/*"android:scheme="content"?/><dataandroid:mimeType="video/*"android:scheme="mms"?/><data?android:mimeType="application/octet-stream"?/><data?android:mimeType="application/x-mpegurl"?/><data?android:mimeType="application/vnd.apple.mpegurl"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><data?android:scheme="content"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><dataandroid:mimeType="application/x-mpegurl"android:scheme="http"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="rtsp"?/><data?android:scheme="rtmp"?/><data?android:scheme="mms"?/><data?android:scheme="tcp"?/><data?android:scheme="udp"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><action?android:name="android.intent.action.SEND"?/><action?android:name="android.intent.action.SENDTO"?/><category?android:name="android.intent.category.DEFAULT"?/><data?android:mimeType="video/*"?/><data?android:mimeType="application/sdp"?/><data?android:mimeType="application/octet-stream"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="http"?/><data?android:mimeType="video/*"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="file"?/><data?android:scheme="content"?/><data?android:scheme="http"?/><data?android:scheme="https"?/><data?android:scheme="ftp"?/><data?android:scheme="rtsp"?/><data?android:scheme="rtmp"?/><data?android:scheme="mms"?/><data?android:scheme="tcp"?/><data?android:scheme="udp"?/><data?android:scheme="gopher"?/><data?android:mimeType="video/*"?/><!--?<data?android:mimeType="audio/*"?/>?--></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="file"?/><data?android:scheme="content"?/><data?android:scheme="http"?/><data?android:scheme="https"?/><data?android:scheme="ftp"?/><data?android:scheme="rtsp"?/><data?android:scheme="rtmp"?/><data?android:scheme="mms"?/><data?android:scheme="tcp"?/><data?android:scheme="udp"?/><data?android:scheme="gopher"?/><data?android:host="*"?/><data?android:pathPattern=".*\\.avi"?/><data?android:pathPattern=".*\\.asf"?/><data?android:pathPattern=".*\\.f4v"?/><data?android:pathPattern=".*\\.flv"?/><data?android:pathPattern=".*\\.mkv"?/><data?android:pathPattern=".*\\.mpeg"?/><data?android:pathPattern=".*\\.mpg"?/><data?android:pathPattern=".*\\.mov"?/><data?android:pathPattern=".*\\.rm"?/><data?android:pathPattern=".*\\.vob"?/><data?android:pathPattern=".*\\.wmv"?/><data?android:pathPattern=".*\\.ts"?/><data?android:pathPattern=".*\\.tp"?/><data?android:pathPattern=".*\\.m3u"?/><data?android:pathPattern=".*\\.m3u8"?/><data?android:pathPattern=".*\\.m4v"?/><data?android:pathPattern=".*\\.mp4"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="rtsp"?/><data?android:mimeType="video/*"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="rtsp"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><category?android:name="android.intent.category.BROWSABLE"?/><data?android:scheme="http"?/><data?android:mimeType="video/*"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><data?android:mimeType="video/*"?/></intent-filter><intent-filter><action?android:name="android.intent.action.VIEW"?/><category?android:name="android.intent.category.DEFAULT"?/><data?android:scheme="file"?/><data?android:mimeType="video/*"?/></intent-filter><intent-filter><action?android:name="android.intent.action.SEARCH"?/><category?android:name="android.intent.category.DEFAULT"?/></intent-filter></activity>
三、監聽視頻播放卡頓時,彈出一個progressbar并提示用戶當前網速
????在這里就要寫一個布局,與視頻播放布局在同一個布局,同樣是include進來
????在system_video_player.xml里加入
<include?layout="@layout/buffering"?android:id="@+id/buffering"/>
? ? 3.1 buffering.xml
????
<?xml?version="1.0"?encoding="utf-8"?>
<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"android:gravity="center"android:visibility="gone"android:padding="3dp"android:layout_centerInParent="true"android:background="#33000000"><ProgressBarandroid:layout_width="30dp"android:layout_height="30dp"/><TextViewandroid:gravity="center"android:id="@+id/tv_netspeed"android:text="緩沖中...30kb/s"android:layout_width="wrap_content"android:layout_height="wrap_content"/></LinearLayout>
? ? 3.2 視頻卡頓時,在Android4.2.2后,系統集成進到了videoview里了,作為一個監聽,那么我們只要實現了這個監聽就可以在里面獲取卡頓時與不卡頓時的回調方法:
????
//監聽網絡播放卡頓現象
if?(Build.VERSION.SDK_INT?>=?Build.VERSION_CODES.JELLY_BEAN_MR1)?{videoview.setOnInfoListener(new?MyOnInfoListener());
}/***?視頻播放卡頓時的監聽,Android4.2.2后封裝到了videoview里了已經*/
public?class?MyOnInfoListener?implements?MediaPlayer.OnInfoListener{@Overridepublic?boolean?onInfo(MediaPlayer?mp,?int?what,?int?extra)?{switch?(what){case?MediaPlayer.MEDIA_INFO_BUFFERING_START:?//開始卡頓//顯示卡頓的布局buffering.setVisibility(View.VISIBLE);break;case?MediaPlayer.MEDIA_INFO_BUFFERING_END:??//結束卡頓buffering.setVisibility(View.GONE);break;}return?true;}
}
這時候,只要是卡頓了,那么就會彈出一個progressbar在視頻中央
? 3.3 在上面的這個,是系統集成好的判斷是否卡頓的方法,那么我們也可以自定義判斷視頻是否卡頓,
????原理是:在handler每一秒循環的消息體中,去判斷當前視頻進度和上一次循環消息時的視頻進度相減,如果進度小魚500ms,那么就判斷是卡頓了,否則就不卡。
????
if?(videoview.isPlaying()){int?buffer=currentPosition-preCurrentPosition;if?(buffer<500){//視頻卡了buffering.setVisibility(View.VISIBLE);}else{buffering.setVisibility(View.GONE);}}else{buffering.setVisibility(View.GONE);
}preCurrentPosition=currentPosition;
????上面的代碼也能判斷視頻卡頓時,顯示progressbar。
四、視頻播放前的loading布局與獲取系統的網速
????原理:寫一個布局,與視頻播放頁面system_video_player.xml在一個布局里,寬高都是match_parent即覆蓋整個屏幕。這樣當點擊播放視頻時,會先顯示這個布局,然后我們再在視頻準備好播放時,讓這個布局消失,即可達到效果
????4.1 system_video_player.xml
<?xml?version="1.0"?encoding="utf-8"?>
<RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:gravity="center"android:background="#000000"android:layout_width="match_parent"android:layout_height="match_parent"><com.yuanlp.mobileplayer.view.MyVideoViewandroid:layout_centerInParent="true"android:id="@+id/videoview"android:layout_width="match_parent"android:layout_height="match_parent"/><!--?loading?視頻卡播放頁面的各種控制按鈕頁面布局--><include?layout="@layout/media_controller"?android:id="@+id/media_controller"/><!--?loading?視頻卡頓時的頁面布局--><include?layout="@layout/buffering"?android:id="@+id/buffering"/>
<!--?loading?頁面布局--><include?layout="@layout/ll_loading"?android:id="@+id/ll_loading"/>
</RelativeLayout>
4.2 在systemVideoPlayer.java里
????
public?void?onPrepared(MediaPlayer?mp)?{videoview.start();?//開始播放duration?=?videoview.getDuration();??//獲取視頻總時長seekbarVideo.setMax(duration);???//設置播放進度的最大值//發送消息,來更新視頻進度handler.sendEmptyMessage(PROGRESS);//設置顯示的視頻總時長tvDuration.setText(utils.stringForTime(duration));//默認進入播放時,隱藏media_controller.setVisibility(View.GONE);isShow=false;??//設置為隱藏//獲取播放器播放視頻的寬度和高度videoHeight=mp.getVideoHeight();videoWidth=mp.getVideoWidth();//?videoview.setVideoSize(mp.getVideoWidth(),mp.getVideoHeight());setVideoType(DEFAULTSCREEN);//當準備好播放時,把loading頁面消失掉ll_loading.setVisibility(View.GONE);}
4.2 獲取網速
????原理是:每次handler2秒循環一次獲取網速消息,在2秒內,獲取的數據量/時間,即可得到網速。
具體代碼如下:
/***?得到網絡速度*?每隔兩秒調用一次*?@param?context*?@return*/
public?String?getNetSpeed(Context?context)?{String?netSpeed?=?"0?kb/s";long?nowTotalRxBytes?=?TrafficStats.getUidRxBytes(context.getApplicationInfo().uid)==TrafficStats.UNSUPPORTED???0?:(TrafficStats.getTotalRxBytes()/1024);//轉為KB;long?nowTimeStamp?=?System.currentTimeMillis();long?speed?=?((nowTotalRxBytes?-?lastTotalRxBytes)?*?1000?/?(nowTimeStamp?-?lastTimeStamp));//毫秒轉換lastTimeStamp?=?nowTimeStamp;lastTotalRxBytes?=?nowTotalRxBytes;netSpeed??=?String.valueOf(speed)?+?"?kb/s";Log.d(TAG,?"當前總的數據"+nowTotalRxBytes);return??netSpeed;
}
這里要在loading布局聲明好時,就立刻發消息,去handler處理,來獲取網速,以便loading界面也出現網速顯示。
????
//加載布局時的布局與網速顯示
ll_loading=?(LinearLayout)?findViewById(R.id.ll_loading);
tv_loading_netspeed=?(TextView)?findViewById(R.id.tv_loading_netspeed);handler.sendEmptyMessage(SPEED);??//控件只要一聲明好就發消息去獲取網速
發完聲明后,就在handler里去處理消息,獲取網速,然后在loading和卡頓時,顯示網速,不卡頓時,隱藏對應的布局
????
public?Handler?handler=new?Handler(){@Overridepublic?void?handleMessage(Message?msg)?{super.handleMessage(msg);switch?(msg.what){case?SPEED:??//顯示當前網速//得到網速String?netSpeed?=?utils.getNetSpeed(SystemVideoPlayer.this);System.out.println("當前網速"+netSpeed);//顯示網速tv_loading_netspeed.setText("玩命加載中"+netSpeed);??//loading時的速度顯示tv_netspeed.setText("緩沖中"+netSpeed);??//緩沖時的速度顯示removeMessages(SPEED);handler.sendEmptyMessageDelayed(SPEED,2000);??//一定要隔2秒才能去獲取網速break;}};
轉載于:https://blog.51cto.com/cm0425/1950630