Exoplayer的简单实现-surfaceView

最近一直在弄这个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 中播放的还未实现、、、、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值