美文网首页Android音视频系列
Android ExoPlayer 填坑之路

Android ExoPlayer 填坑之路

作者: 土肥圆的诺诺 | 来源:发表于2019-03-03 20:06 被阅读4次

    自从上次做完视频播放器调研以后,心里就知道,肯定以后这块东西都是我做,果不其然,公司对视频播放这块不断的优化。我就悲催的无限填坑,话说英语差,看国外文档真的很吃力。
    简单讲一下项目中遇到的问题。

    • 创建和基本使用
      这个不多讲,最简单使用就是布局里
     <com.google.android.exoplayer2.ui.PlayerView
                    android:id="@+id/videoview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    app:surface_type="texture_view"
                    app:use_controller="false" />
    

    接下来创建轨道,播放器等,如果你播放的时候发现有时候黑屏。这是可能你的VideoCache不是单例模式。 下面是我自己写的Manger和VideoCache

    public class ExoPlayerManger {
        private static final String TAG = "ExoPlayerManger";
        private Context mContext;
        private  BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        // 创建轨道选择工厂
        private TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        // 创建轨道选择器实例
        private TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
        private SimpleExoPlayer simpleExoPlayer;
        private DataSource.Factory dataSourceFactory;
        private String mVideoUrl;
        private SimpleCache simpleCache;
        private Uri playVideoUri;
        private ExtractorMediaSource mediaSource;
    
    
        /**
         * @param context 传入context
         */
        public void setBuilderContext(Context context) {
            mContext = context;
            dataSourceFactory = new DefaultDataSourceFactory(mContext, "seyed");
        }
    
        /**
         * @param videoUrl 传入视频路径
         */
        public void setVideoUrl(String videoUrl) {
            this.mVideoUrl = videoUrl;
            simpleCache = VideoCache.getInstance(mContext);
            playVideoUri = Uri.parse(mVideoUrl);
        }
    
    
        /**
         * @return 返回exoPlayer对象
         */
        public SimpleExoPlayer create() {
            try {
                simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);
                dataSourceFactory = new CacheDataSourceFactory(simpleCache, dataSourceFactory);
                mediaSource = new ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(playVideoUri);
                simpleExoPlayer.prepare(mediaSource);
    
            } catch (Exception e) {
    
            }
            return simpleExoPlayer;
        }
    
    
    }
    
    
    
    /**
     * @author :leo on 2018/12/17 17:58
     * <p>
     * 方法用途 :视频缓存单例模式
     */
    public class VideoCache {
        private static SimpleCache sDownloadCache;
    
        /**
         * @param context
         * @return
         */
        public static SimpleCache getInstance(Context context) {
            if (sDownloadCache == null) {
                sDownloadCache = new SimpleCache(new File(getMediaCacheFile(context), "StoryCache"), new LeastRecentlyUsedCacheEvictor(512 * 1024 *1024));
    
            }
            return sDownloadCache;
        }
    
        public static File getMediaCacheFile(Context context) {
            String directoryPath = "";
            String childPath = "exoPlayer";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                // 外部储存可用
                directoryPath = File.separator + context.getExternalFilesDir(childPath).getAbsolutePath();
            } else {
                directoryPath = File.separator + context.getFilesDir().getAbsolutePath() + File.separator + childPath;
            }
            File file = new File(directoryPath);
            //判断文件目录是否存在
            if (!file.exists()) {
                file.mkdirs();
            }
    
            return file;
        }
    
    
    }
    
    

    紧接着 只需要

    ExoPlayerManger exoPlayerManger = new ExoPlayerManger();
            exoPlayerManger.setBuilderContext(mContext);
            exoPlayerManger.setVideoUrl(playVideoUrl);
            simpleExoPlayer = exoPlayerManger.create();
            //设置音量  测试期间设置为0
            simpleExoPlayer.setVolume(10);
            videoView.setPlayer(simpleExoPlayer);
            //赋值给显示时间
            simpleExoPlayer.addListener(this);
          //开启播放
            simpleExoPlayer.setPlayWhenReady(true);
    

    播放器有个监听 Player.EventListener ,这就讲几个状态

    @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            if (isFullScreen) {
                fullScreenDialog.setPlayState(playbackState);
            }
            switch (playbackState) {
            //缓冲状态
                case 2:
                    break;
                //播放状态
                case 3:
                 
                    break;
                //播放完成
                case 4:
                   
                default:
                    break;
            }
    
    
    • 如何播放raw下文件
      RawResourceDataSource.buildRawResourceUri(R.raw.login_bg_video);
            ExoPlayerManger exoPlayerManger = new ExoPlayerManger();
            exoPlayerManger.setBuilderContext(getContext());
    //设置从raw下读取的文件路径
       exoPlayerManger.setVideoUrl(RawResourceDataSource.buildRawResourceUri(R.raw.login_bg_video).toString());
            simpleExoPlayer = exoPlayerManger.create();
            simpleExoPlayer.setVolume(0);
            simpleExoPlayer.setRepeatMode(1);
            playerView.setPlayer(simpleExoPlayer);
    
    //        simpleExoPlayer.prepare(audioSource);
    
            simpleExoPlayer.setPlayWhenReady(true);
    
    • 列表中点击切换到全屏
      这里有很多方法,我选择的方法不是最好的。科学上网看了很多老外写的例子,大部分都是弹出一个Dialog,将item中的播放PlayerView,remove出来,放到Dialog里面。然后更改PlayerView的布局大小就可以了。
      但是这里会有一个卡顿问题,老外同学们基本没讲,如果你按照直接removeView然后addView to Dialog, 我测试基本会卡1-5s。这时候可以做一个骚操作,就是向前或者向后seekto一下,可以基本做到秒开。当你切换窗口的时候,可以将PlayerView 还回去就可以了,记得设置原来的宽高和大小。
     //从当前布局移除播放view
            ViewGroup parent = (ViewGroup) videoView.getParent();
            if (parent != null) {
                parent.removeView(videoView);
            }
    
    //加入到Dialog
     ViewGroup.LayoutParams layoutParams = videoView.getLayoutParams();
            layoutParams.width = RelativeLayout.LayoutParams.MATCH_PARENT;
            layoutParams.height = RelativeLayout.LayoutParams.MATCH_PARENT;
            videoView.setLayoutParams(layoutParams);
            rlShow.addView(playerView);
    
    

    其实也可以尝试使用,simpleExoPlayer.setVideoTextureView();切换画布,但是我在测试的时候,会有卡顿,有时间的同学可以试试,希望你有别的办法可以给我留言,谢谢。还有很多细节的东西,等我想起来再补上,连续加班,今天才有时间写点东西,就先到这里 。


    相关文章

      网友评论

        本文标题:Android ExoPlayer 填坑之路

        本文链接:https://www.haomeiwen.com/subject/shpmuqtx.html