美文网首页Android开发经验谈Android开发半栈工程师
JiaoZiVideoPlayer使用说明(持续更新中...)

JiaoZiVideoPlayer使用说明(持续更新中...)

作者: 大明小明Cj | 来源:发表于2018-08-22 13:49 被阅读712次

饺子视频播放器使用说明 Github

主要特点

  1. 可以完全自定义UI和任何功能
  2. 一行代码切换播放引擎,支持的视频格式和协议取决于播放引擎,android.media.MediaPlayer ijkplayer
  3. 完美检测列表滑动
  4. 可实现全屏播放,小窗播放
  5. 能在ListView、ViewPager和ListView、ViewPager和Fragment等多重嵌套模式下全屏工作
  6. 可以在加载、暂停、播放等各种状态中正常进入全屏和退出全屏
  7. 多种视频适配屏幕的方式,可铺满全屏,可以全屏剪裁
  8. 重力感应自动进入全屏
  9. 全屏后手势修改进度和音量
  10. Home键退出界面暂停播放,返回界面继续播放
  11. WebView嵌套本地视频控件
  12. demo中添加视频缓存的例子

集成使用

即便是自定义UI,或者对Library有过修改,也是这五步骤来使用播放器。

1.添加类库

compile 'cn.jzvd:jiaozivideoplayer:6.2.12'

2.添加布局
<cn.jzvd.JZVideoPlayerStandard
    android:id="@+id/videoplayer"
    android:layout_width="match_parent"
    android:layout_height="200dp"/>
3.设置视频地址、缩略图地址、标题
JZVideoPlayerStandard jzVideoPlayerStandard = (JZVideoPlayerStandard) findViewById(R.id.videoplayer);
jzVideoPlayerStandard.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4"
                            , JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL, "饺子闭眼睛");
jzVideoPlayerStandard.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640
这里只是告诉你缩略图该怎么设置,库中没有该方法,推荐使用Glide
4.在Activity中

@Override
public void onBackPressed() {
    if (JZVideoPlayer.backPress()) {
        return;
    }
    super.onBackPressed();
}
@Override
protected void onPause() {
    super.onPause();
    JZVideoPlayer.releaseAllVideos();  
}
在AndroidManifest.xml中
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:screenOrientation="portrait" /> <!-- or android:screenOrientation="landscape"-->

好了官方文档说明CV完了,下面就该介绍我们实际开发中遇到的问题和奇葩的需求实现。 image

基本使用

  1. 加缩略载图
Glide.with(this).load(Url).into(myJZVideoPlayerStandard.thumbImageView);   //推荐使用Glide
  1. 自动播放
1. mJZVideoPlayerStandard.startButton.performClick();
2. myJZVideoPlayerStandard.startVideo();

2.播放sd卡下视频

public void cpAssertVideoToLocalPath() {
        try {
            InputStream myInput;
            OutputStream myOutput = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "local_video.mp4");
            myInput = this.getAssets().open("local_video.mp4");
            byte[] buffer = new byte[1024];
            int length = myInput.read(buffer);
            while (length > 0) {
                myOutput.write(buffer, 0, length);
                length = myInput.read(buffer);
            }

            myOutput.flush();
            myInput.close();
            myOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }    
mJzVideoPlayerStandard.setUp(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/local_video.mp4", JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL, "饺子不信");
这里很多人问为什么播不了,请认真怒url,播不了就是url没怒对

播放assets目录下的视频

       复制Demo中CustomMediaPlayerAssertFolder类到你的项目下
        ----------------------------------------------------------------------------
        LinkedHashMap map = new LinkedHashMap();
        try {
            map.put(JZVideoPlayer.URL_KEY_DEFAULT, getAssets().openFd("local_video.mp4"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Object[] dataSourceObjects = new Object[2];
        dataSourceObjects[0] = map;
        dataSourceObjects[1] = this;
        JZVideoPlayerStandard.startFullscreen(this, JZVideoPlayerStandard.class, dataSourceObjects, 0, "")
        JZVideoPlayer.setMediaInterface(new CustomMediaPlayerAssertFolder());

直接全屏播放

JZVideoPlayerStandard.startFullscreen(this, JZVideoPlayerStandard.class, "url", "饺子辛苦了");

开启小窗播放

mJzVideoPlayerStandard.startWindowTiny();

列表Item划出开启小窗播放

1.Listview
   listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) { 

            }
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                JZVideoPlayer.onScrollAutoTiny(view, firstVisibleItem, visibleItemCount, totalItemCount);
              //  JZVideoPlayer.onScrollReleaseAllVideos(view, firstVisibleItem, visibleItemCount, totalItemCount);  这是不开启列表划出小窗 同时也是画出屏幕释放JZ
            }
        });
2. RecyclerView
   recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(View view) {
                JZVideoPlayer.onChildViewAttachedToWindow(view, R.id.videoplayer);
            }

            @Override
            public void onChildViewDetachedFromWindow(View view) {
                JZVideoPlayer.onChildViewDetachedFromWindow(view);
            }
        });
2.1 RecyclerView划出屏幕释放JZ,同时也是不开启列表划出显示小窗
    recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(View view) {

            }

            @Override
            public void onChildViewDetachedFromWindow(View view) {
                JZVideoPlayer jzvd = view.findViewById(R.id.videoplayer);
                if (jzvd != null && JZUtils.dataSourceObjectsContainsUri(jzvd.dataSourceObjects, JZMediaManager.getCurrentDataSource())) {
                    JZVideoPlayer currentJzvd = JZVideoPlayerManager.getCurrentJzvd();
                    if (currentJzvd != null && currentJzvd.currentScreen != JZVideoPlayer.SCREEN_WINDOW_FULLSCREEN) {
                        JZVideoPlayer.releaseAllVideos();
                    }
                }
            }
        });

小屏播放无声音,全屏有声音

创建一个类集成JZVideoPlayerStandard 并在XML设置
public class JZVideoPlayerStandardVolumeAfterFullscreen extends JZVideoPlayerStandard {
    public JZVideoPlayerStandardVolumeAfterFullscreen(Context context) {
        super(context);
    }

    public JZVideoPlayerStandardVolumeAfterFullscreen(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onPrepared() {
        super.onPrepared();
        if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
            JZMediaManager.instance().jzMediaInterface.setVolume(1f, 1f);
        } else {
            JZMediaManager.instance().jzMediaInterface.setVolume(0f, 0f);
        }
    }

    /**
     * 进入全屏模式的时候关闭静音模式
     */
    @Override
    public void startWindowFullscreen() {
        super.startWindowFullscreen();
        JZMediaManager.instance().jzMediaInterface.setVolume(1f, 1f);
    }

    /**
     * 退出全屏模式的时候开启静音模式
     */
    @Override
    public void playOnThisJzvd() {
        super.playOnThisJzvd();
        JZMediaManager.instance().jzMediaInterface.setVolume(0f, 0f);
    }
}

全屏状态播放完成,不退出全屏

创建一个类集成JZVideoPlayerStandard 并在XML设置
public class JZVideoPlayerStandardAutoCompleteAfterFullscreen extends JZVideoPlayerStandard {
    public JZVideoPlayerStandardAutoCompleteAfterFullscreen(Context context) {
        super(context);
    }

    public JZVideoPlayerStandardAutoCompleteAfterFullscreen(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void startVideo() {
        if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
            Log.d(TAG, "startVideo [" + this.hashCode() + "] ");
            initTextureView();
            addTextureView();
            AudioManager mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
            mAudioManager.requestAudioFocus(onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
            JZUtils.scanForActivity(getContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            JZMediaManager.setDataSource(dataSourceObjects);
            JZMediaManager.setCurrentDataSource(JZUtils.getCurrentFromDataSource(dataSourceObjects, currentUrlMapIndex));
            JZMediaManager.instance().positionInList = positionInList;
            onStatePreparing();
        } else {
            super.startVideo();
        }
    }

    @Override
    public void onAutoCompletion() {
        if (currentScreen == SCREEN_WINDOW_FULLSCREEN) {
            onStateAutoComplete();
        } else {
            super.onAutoCompletion();
        }

    }
}

Home键退出界面暂停播放,返回界面继续播放

  @Override
    protected void onResume() {
        super.onResume();
        //home back
        JZVideoPlayer.goOnPlayOnResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        JZVideoPlayer.clearSavedProgress(this, null);
        //home back
        JZVideoPlayer.goOnPlayOnPause();
    }

边播边缓存和清晰度切换

1. 集成videocache implementation 'com.danikula:videocache:2.7.0',并初始化
public class ApplicationDemo extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
//        LeakCanary.install(this);

    }

    private HttpProxyCacheServer proxy;

    public static HttpProxyCacheServer getProxy(Context context) {
        ApplicationDemo app = (ApplicationDemo) context.getApplicationContext();
        return app.proxy == null ? (app.proxy = app.newProxy()) : app.proxy;
    }

    private HttpProxyCacheServer newProxy() {
        return new HttpProxyCacheServer(this);
    }
}
2.引用
       LinkedHashMap map = new LinkedHashMap();
        String proxyUrl = ApplicationDemo.getProxy(this).getProxyUrl(VideoConstant.videoUrls[0][9]);
        // 这是各个清晰度URL
        map.put("高清", proxyUrl);          //这里是边播边缓存 
        map.put("标清", VideoConstant.videoUrls[0][6]);    
        map.put("普清", VideoConstant.videoUrlList[0]);
        Object[] objects = new Object[3];
        objects[0] = map;
        objects[1] = false;//looping    //这里是重复播放的标志 
        objects[2] = new HashMap<>();
       // ((HashMap) objects[2]).put("key", "value");//header
        mJzVideoPlayerStandard.setUp(objects, 2
                , JZVideoPlayerStandard.SCREEN_WINDOW_NORMAL, "饺子不信");

重复播放

创建一个类集成JZVideoPlayerStandard 并在XML设置
public class JZVideoPlayerStandardLoopVideo extends JZVideoPlayerStandard {
    public JZVideoPlayerStandardLoopVideo (Context context) {
        super(context);
    }

    public JZVideoPlayerStandardLoopVideo (Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onAutoCompletion() {
        super.onAutoCompletion();
        startVideo();
    }
}
还有一种方法就是上面清晰度切换loop循环标志

重力感应自动进入全屏

    SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    JZVideoPlayer.JZAutoFullscreenListener mSensorEventListener = new JZVideoPlayer.JZAutoFullscreenListener();
    @Override
    protected void onResume() {
        super.onResume();
        Sensor accelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mSensorManager.registerListener(mSensorEventListener, accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(mSensorEventListener);
   }

重力感应

JZVideoPlayer.FULLSCREEN_ORIENTATION=ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
JZVideoPlayer.NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
两个变量控制全屏前后的屏幕方向

不保存播放进度

JZVideoPlayer.SAVE_PROGRESS = false;

取消播放时4GDialog提示

JZVideoPlayer.WIFI_TIP_DIALOG_SHOWED=true;

清除某个URL进度

 JZVideoPlayer.clearSavedProgress(this, "url");

获取视频某一帧

/**
* [@param](https://github.com/param) context 上下文
* [@param](https://github.com/param) uri 视频地址
* [@param](https://github.com/param) imageView 设置image
* [@param](https://github.com/param) frameTimeMicros 获取某一时间帧
*/
public static void loadVideoScreenshot(final Context context, String uri, ImageView imageView, long frameTimeMicros) {
    RequestOptions requestOptions = RequestOptions.frameOf(frameTimeMicros);
    requestOptions.set(FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST);
    requestOptions.transform(new BitmapTransformation() {
        @Override
        protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
            return toTransform;
        }
        @Override
        public void updateDiskCacheKey(MessageDigest messageDigest) {
            try {
                messageDigest.update((context.getPackageName() + "RotateTransform").getBytes("utf-8"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
    Glide.with(context).load(uri).apply(requestOptions).into(imageView);
}

切换播放内核

ijk
    复制Demo中JZMediaIjkplayer类到你的项目下 
    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
MediaPlayer
    JZVideoPlayer.setMediaInterface(new JZMediaIjkplayer());  //  ijk
    JZVideoPlayer.setMediaInterface(new JZMediaSystem());  // 
exo
    复制Demo中JZExoPlayer类到你的项目下 
    implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
    JZVideoPlayer.setMediaInterface(new JZExoPlayer());  //exo

常见问题

相关状态函数回调讲解

自定义UI

一些奇葩需求实现

JZVideoPlayer源码讲解

相关文章

  • JiaoZiVideoPlayer使用说明(持续更新中...)

    饺子视频播放器使用说明 Github 主要特点 可以完全自定义UI和任何功能 一行代码切换播放引擎,支持的视频格...

  • 2018-05-01

    JiaoZiVideoPlayer黑边问题的解决 上面的截图来自jiaozivideoplayer的github上...

  • Android第三方开源播放器使用ijk内核的若干问题

    1.JiaoZiVideoPlayer现已升级JiaoZiVideoPlayer 问(这个问题还是2018年的哈哈...

  • 持续更新中……

    【洗脸小常识️】 洗脸方法正确才能减少皱纹、延缓衰老: ❶、 洗脸前先洗手 ❷、 用❸❺℃左右温水洗脸 ❸、记得洗...

  • 持续更新中…

    合并报表进行中,我的双眼不在状态,笔杆儿也快撑不住我的脑袋,课件怎么这么难,工作压力怎么这么大。 看着壮实的大王,...

  • 持续更新中

    酒逢知己饮、望断天涯事 何日得浮生,偷得半日闲 持续码字中的感觉:文字是一扇窗,当你打开着这扇窗时,你我之间就开始...

  • 持续更新中

    持续更新中,我想了一下,要是哪一天没有写的,可不可以就写一个字,然后一直重复下去呢?就像这样:爱爱爱爱……这样可以...

  • 持续更新中

    朝七晚十,累,调整中 !

  • 《Java编程思想》

    持续更新中

  • linux 查看文件夹大小

    ...持续更新中

网友评论

  • Yet_land:使用播放器,第一次播放成功,第二次必定播放失败。这会是什么原因?10-17 15:50:17.997 14727-14727/com.dtdream.awjgovernment W/MediaPlayerNative: Stream has no duration and is therefore not seekable.
    10-17 15:50:17.997 14727-14727/com.dtdream.awjgovernment D/MediaPlayerNative: Message: MEDIA_ERROR(100), ext1=Unknown MediaErrorType(-2147483648), ext2=0x0
    10-17 15:50:17.997 14727-14727/com.dtdream.awjgovernment E/MediaPlayerNative: error (-2147483648, 0)
    10-17 15:50:17.997 14727-14727/com.dtdream.awjgovernment D/MediaPlayerNative: [notify] : [1237] callback app listenerNotNull=1, send=1
    [notify] : [1254] callback application
    10-17 15:50:17.997 14727-14727/com.dtdream.awjgovernment I/JZVD: onStatePlaying [214284882]
    10-17 15:50:17.997 14727-15053/com.dtdream.awjgovernment E/MediaPlayer: Error (-2147483648,0)
    10-17 15:50:17.998 14727-14727/com.dtdream.awjgovernment I/JZVD: startProgressTimer: [214284882]
    10-17 15:50:17.998 14727-15053/com.dtdream.awjgovernment I/MediaPlayer: [HSM] stayAwake false uid: 10171, pid: 14727
    10-17 15:50:18.003 14727-14727/com.dtdream.awjgovernment E/JZVD: onError -2147483648 - 0 [214284882]
    10-17 15:50:18.003 14727-14727/com.dtdream.awjgovernment I/JZVD: onStateError [214284882]
    Yet_land:@大明小明C 他第二次播放的时候,还会报getDuration的问题
    大明小明Cj:@Yet_land 链接放demo试试,,不行换ijk试试,
  • 和你的烩忆:请问下,我播放视频只播放一半然后就退出后activity也有走Jzvd.releaseAllVideos();为什么把app关掉之后重新打开然后去点视频还是之前播放的位置?数据没有清空
    大明小明Cj:@和你的烩忆 看上面的文档,,不保存播放进度,
  • 痴迷_d6b5:请问大佬有遇到过这种问题吗,就是视频播放是画面和音频不同步,用的也是jiaozi,求解
    痴迷_d6b5:@大明小明C 好的 我试一下
    大明小明Cj:@痴迷_d6b5 首先确保视频本身有无问题如果没有,,换ijk试试,如果有问题百度ijk音视频不同步问题,ijk有解决方案。,这个是硬解码问题,
  • 程序员能有什么坏心思:myJzvdStd.setUp(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/local_video.mp4",

    这个本地SDK的确实播放不来,我都确认过文件地址是存在的,
    程序员能有什么坏心思:可以了,是我7.0应用权限没放开导致的,尴尬了,哈哈
    大明小明Cj:@1cf33407c158 测试过我才放上去的,请认真检查url
  • markRao:请教一个问题,viewpage里fragment里rc放播放器,切换fragment怎么暂停播放???求解,谢谢
    markRao:@大明小明C 多谢了😄😄😄
    大明小明Cj:@萬物並作吾以觀復 在onpageselecter 回调里面释放饺子(Jzvd.releaseAllVideos),,或者判断fragment是否见,在释放饺子
    Jzvd.goonplayonpause是暂停的方法,
  • 612ac448a3a4:wifi 网络下 好使,4G 网络下 加载视频失败
    ........ 快快快
  • MardaWang:我这边遇到一个问题,小屏的时候有根据需求判断是否可以快进回退,但是切换到全屏的时候,视频都可以快进回退,设置无效了,你这边可知道怎么处理?
  • 612ac448a3a4:JiaoZiVideoPlayer 不能铺满控件呢 快快快.....
    612ac448a3a4:@嗨嗨明明1 JZVideoPlayerStandard.setVideoImageDisplayType(JZVideoPlayerStandard.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT);
    e9f2770b46ef:<android.support.v4.view.ViewPager
    android:id="@+id/main_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />//原本是写死的200dp
    大明小明Cj:铺满空间 什么意思
  • e9f2770b46ef:设置了硬件加速 android:hardwareAccelerated 老是播放不了 去掉就可以了
    OyeAndroid:我也遇到了这个问题,关掉以后就一直加载,所以硬件加速 android:hardwareAccelerated得打开才行
    e1c25d29bdaf:去掉默认是开启,要开启硬件加速才能播,否则一直加载
  • ff2db7a474c4:大神,请教一下,用这个播放网络视频,在同一个页面,我先播放一个视频,没有任何问题,但是切换另一个视频地址,然后在按全屏播放就闪退了.请问何解?
    MardaWang:我这边也有这种情况
    :sweat:
    大明小明Cj:@WHAT_b8ab 群号490442439
    ff2db7a474c4:@C大明小明 GitHub上的qq我都加了,没反应

本文标题:JiaoZiVideoPlayer使用说明(持续更新中...)

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