最近一直在弄這個Exoplayer,官方的實在是太全面了、在GitHub庫中下來的demo在我這跑不起來、實在是讓我好憂傷。官方demo的PlayerActivity寫的很全面,但原諒我有些分不清它們的具體功能,是以我删除掉好多、八百多行的代碼最後隻剩下接近三百多行、、、
首先、來一段官方的描述:
ExoPlayer是Android應用程式級别的媒體播放器。
它提供了播放音頻和視訊本地和在網際網路上Android的MediaPlayer的API的替代品。
ExoPlayer不支援目前Android的MediaPlayer的API,包括儀表闆和SmoothStreaming自适應播放支援的功能。
不同的是MediaPlayer的API,ExoPlayer容易定制和擴充,并且可以通過Play商店應用程式更新進行更新。
文檔
該開發人員指南提供了豐富的資訊,以幫助您開始。
本類引用記錄了ExoPlayer庫類。
項目首頁-項目首頁
GitHub的項目 -包含源代碼,還有一個示範應用程式。
使用ExoPlayer
通過jCenter
最簡單的方式開始使用ExoPlayer是通過在項目的build.gradle檔案:
編譯“com.google.android.exoplayer:exoplayer:rX.XX” 其中, rX.XX是您的首選版本。
有關最新版本,請參閱該項目的釋出 。 有關詳細資訊,請參閱該項目Bintray 。
由于library
ExoPlayer也可以從源使用Gradle建構的。 你可以把它作為像這樣一個相關項目:
// settings.gradle
include ‘:app’, ‘:..:ExoPlayer:library’
// app/build.gradle dependencies {
compile project(‘:..:ExoPlayer:library’) }
如果你想使用ExoPlayer作為 jar 運作:
./gradlew jarRelease 并複制library.jar到新項目的libs檔案夾。
我使用的是第一個方法,即在項目的build.gradle檔案中編譯“com.google.android.exoplayer:exoplayer:rX.XX”
完成後在項目的External Libraries中:
然後在官方的demo中複制了一下檔案:
ExtractorSampleSource -對于格式,如FMP4,MP4,M4A,MKV,WebM功能,支援MP3,AAC,MPEG-TS,MPEG-PS,OGG,FLV和WAV。
HlsSampleSource - HLS 播放
它們的用途可以看 開發者指南、、、
在我的OnePlayerActivity實作了一個視訊的播放(包括全屏播放)
contentUri 是視訊的uri播放位址
contentType 是流媒體傳輸協定類型,可以支援DASH和HLS以及OTHER類型
//擷取視訊資料
private void onShown() {
contentUri = Uri.parse("http://devimages.apple.com/samplecode/adDemo/ad.m3u8");
//contentUri = Uri.parse("http://html5demos.com/assets/dizzy.mp4");
//inferContentType根據uri的字尾判斷
contentType = inferContentType(contentUri);
Log.e("TAG", "contentUri" + contentUri + "contentType" + contentType);
if (player == null) {
//if (!maybeRequestPermission()) { 檢查權限,6.0以上可以動态擷取權限
preparePlayer(true);
//}
} else {
player.setBackgrounded(false);
}
}
初始化準備player,addListener添加監聽,如播放的狀态onStateChanged,視訊大小變化onVideoSizeChanged, 出現錯誤onError,
private void preparePlayer(boolean playWhenReady) {
if (player == null) {
player = new DemoPlayer(getRendererBuilder());
player.addListener(this);
player.seekTo(playerPosition);//播放進度的設定 一開始為0
playerNeedsPrepare = true; //是否立即播放
}
if (playerNeedsPrepare) {
player.prepare();
playerNeedsPrepare = false;
}
player.setSurface(surfaceView.getHolder().getSurface());
player.setPlayWhenReady(playWhenReady);
}
官方的PlayerActivity中使用的媒體控制器使用的是goole的MediaController,好用,但沒有全屏、、、
//初始化對象以及依附父布局root,View
mediaController = new KeyCompatibleMediaController(this);
mediaController.setAnchorView(root);
...
//自定義KeyCompatibleMediaController 媒體控制類,繼承于MediaController
private static final class KeyCompatibleMediaController extends MediaController {
private MediaController.MediaPlayerControl playerControl;
public KeyCompatibleMediaController(Context context) {
super(context);
}
@Override
public void setMediaPlayer(MediaController.MediaPlayerControl playerControl) {
super.setMediaPlayer(playerControl);
this.playerControl = playerControl;
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
//這是前進和後退按鈕、、、
if (playerControl.canSeekForward() && (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|| keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
playerControl.seekTo(playerControl.getCurrentPosition() + ); // milliseconds
show();
}
return true;
} else if (playerControl.canSeekBackward() && (keyCode == KeyEvent.KEYCODE_MEDIA_REWIND
|| keyCode == KeyEvent.KEYCODE_DPAD_LEFT)) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
playerControl.seekTo(playerControl.getCurrentPosition() - ); // milliseconds
show();
}
return true;
}
return super.dispatchKeyEvent(event);
}
...
//關聯player
mediaController.setMediaPlayer(player.getPlayerControl());
mediaController.setEnabled(true);
但在我的OnePlayerActivity中沒有使用這個,而是自己寫的,當然布局、圖檔什麼的要自己提供了
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.py://播放鍵
if(player.getPlayWhenReady()){
py.setBackground(getResources().getDrawable(R.drawable.pause));
player.setPlayWhenReady(false);
}else {
py.setBackground(getResources().getDrawable(R.drawable.player));
player.setPlayWhenReady(true);
}
break;
case R.id.fs://全屏鍵
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {//橫屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
fs.setBackground(getResources().getDrawable(R.drawable.full));
} else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){//豎屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
fs.setBackground(getResources().getDrawable(R.drawable.lessen));
}
break;
}
}
SeekBar實作監聽後,使用Player的seekTo來控制視訊的播放進度、
用seekBar.setProgress(msg.arg1);來設定seekbar的進度,
在視訊狀态監聽中的開始播放時可以擷取到視訊的長度,Player.getDuration();(也可以擷取到視訊的寬高等)
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {//放開
player.seekTo(seekBar.getProgress());
}
});
使用SurfaceView在進入這個activity時會出現一會兒的黑屏,這是因為SurfaceView因為不同于一般的view,它有自己良好的緩沖以及資料存取機制,系統對他有特殊處理。當surfaceview第一次在目前activity上添加的時候,系統會給WindowManager重新排布局,relayout,這樣就會黑一下,這個隻會出現在第一次,以後再添加surfaceview時就不會黑屏了。
生命周期及調用流程:
這裡需要注意的一點是在調用Exoplayer的playWhenReady接口時需要等到surfaceView的surfaceCreated後才能調用, 否則會失敗.
最後,感謝您的閱讀、、、
MyExoplayer:http://download.csdn.net/detail/zp0203/9600650 隻有一個視訊播放的,listView 中播放的還未實作、、、、