最近一直在弄这个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() + 15000); // 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() - 5000); // 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 中播放的还未实现、、、、