JiaoziVideoPlayer 7版本使用说明(持续更新中...)

上官思博
2023-12-01

饺子视频播放器使用说明

主要特点

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

集成使用

即便是自定义UI,或者对Library有过修改,把自定义的逻辑写到继承JzvdStd的类中,然后依然通过如下骤调用播放器。

1.添加类库

compile 'cn.jzvd:jiaozivideoplayer:release'

2.添加布局

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">
    <cn.jzvd.demo.CustomJzvd.MyJzvdStd
        android:id="@+id/jz_video"
        android:layout_width="match_parent"
        android:layout_height="200dp" />
</LinearLayout>
复制代码

3.设置视频地址、缩略图地址、标题

MyJzvdStd jzvdStd = (MyJzvdStd) findViewById(R.id.jz_video);
jzvdStd.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4"
                            , "饺子闭眼睛");
jzvdStd.thumbImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
复制代码
4.在Activity中
 @Override
    protected void onPause() {
        super.onPause();
        Jzvd.resetAllVideos();
    }

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

在proguard-rules.pro中按需添加

-keep public class cn.jzvd.JZMediaSystem {*; }
-keep public class cn.jzvd.demo.CustomMedia.CustomMedia {*; }
-keep public class cn.jzvd.demo.CustomMedia.JZMediaIjk {*; }
-keep public class cn.jzvd.demo.CustomMedia.JZMediaSystemAssertFolder {*; }

-keep class tv.danmaku.ijk.media.player.** {*; }
-dontwarn tv.danmaku.ijk.media.player.*
-keep interface tv.danmaku.ijk.media.player.** { *; }
复制代码

基本使用

加缩略载图

Glide.with(this).load(Url).into(myJzvdStd.thumbImageView);   //推荐使用Glide
复制代码

自动播放

  自动播放有两种 这里随便选择添加一个,
1. myJzvdStd.startButton.performClick();
2. myJzvdStd.startVideo();
复制代码

跳转制定位置播放

//这里只有开始播放时才生效
mJzvdStd.seekToInAdvance = 20000;
复制代码

2.播放sd卡下视频

 mJzvdStd.setUp(Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/local_video.mp4", "饺子不信", Jzvd.SCREEN_NORMAL);
这里很多人问为什么播不了,请认真怒url,播不了就是url没怒对
复制代码

播放assets目录下的视频

复制Demo中JZMediaSystemAssertFolder类到你的项目下
----------------------------------------------------------------------------
JZDataSource jzDataSource = null;
try {
      jzDataSource = new JZDataSource(getAssets().openFd("local_video.mp4"));
      jzDataSource.title = "饺子快长大";
} catch (IOException e) {
      e.printStackTrace();
}
 jzvdStd.setUp(jzDataSource, JzvdStd.SCREEN_NORMAL, JZMediaSystemAssertFolder.class);
复制代码

直接全屏播放

JzvdStd.startFullscreenDirectly(this, JzvdStd.class, VideoConstant.videoUrlList[6], "饺子辛苦了");
复制代码

开启小窗播放

 mJzvdStd.gotoScreenTiny();
复制代码

列表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) {
                if (Jzvd.CURRENT_JZVD == null) return;
                int lastVisibleItem = firstVisibleItem + visibleItemCount;
                int currentPlayPosition = Jzvd.CURRENT_JZVD.positionInList;
//                Log.e(TAG, "onScrollReleaseAllVideos: " +
//                        currentPlayPosition + " " + firstVisibleItem + " " + currentPlayPosition + " " + lastVisibleItem);
                if (currentPlayPosition >= 0) {
                    if ((currentPlayPosition < firstVisibleItem || currentPlayPosition > (lastVisibleItem - 1))) {
                        if (Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
                            Jzvd.resetAllVideos();//为什么最后一个视频横屏会调用这个,其他地方不会
                        }
                    }
                }
            }
        });
2. RecyclerView  划出列表开启小窗
 recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(View view) {//这个的本质是gotoThisJzvd,不管他是不是原来的容器
                //如果这个容器中jzvd的url是currentJzvd的url,那么直接回到这里,不用管其他的
                JzvdStdTinyWindow jzvd = view.findViewById(R.id.videoplayer);
                JzvdStdTinyWindow currentJzvd = (JzvdStdTinyWindow) Jzvd.CURRENT_JZVD;
                if (jzvd != null && currentJzvd != null &&
                        jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())
                        && Jzvd.CURRENT_JZVD.state == Jzvd.STATE_PLAYING) {
                    ViewGroup vp = (ViewGroup) jzvd.getParent();
                    vp.removeAllViews();
                    ((ViewGroup) currentJzvd.getParent()).removeView(currentJzvd);
                    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                    vp.addView(currentJzvd, lp);
                    currentJzvd.setScreenNormal();
                    Jzvd.CONTAINER_LIST.pop();
                }
            }

            @Override
            public void onChildViewDetachedFromWindow(View view) {
                JzvdStdTinyWindow jzvd = view.findViewById(R.id.videoplayer);
                if (jzvd != null && Jzvd.CURRENT_JZVD != null &&
                        jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())
                        && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_TINY) {
                    if (Jzvd.CURRENT_JZVD.state == Jzvd.STATE_PAUSE) {
                        Jzvd.resetAllVideos();
                    } else {
                        ((JzvdStdTinyWindow) Jzvd.CURRENT_JZVD).gotoScreenTiny();
                    }
                }
            }
        });
2.1 RecyclerView划出屏幕释放JZ,同时也是不开启列表划出显示小窗
    recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
            @Override
            public void onChildViewAttachedToWindow(View view) {

            }

            @Override
            public void onChildViewDetachedFromWindow(View view) {
                Jzvd jzvd = view.findViewById(R.id.videoplayer);
                if (jzvd != null && Jzvd.CURRENT_JZVD != null &&
                        jzvd.jzDataSource.containsTheUrl(Jzvd.CURRENT_JZVD.jzDataSource.getCurrentUrl())) {
                    if (Jzvd.CURRENT_JZVD != null && Jzvd.CURRENT_JZVD.screen != Jzvd.SCREEN_FULLSCREEN) {
                        Jzvd.resetAllVideos();
                    }
                }
            }
        });
复制代码

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

创建一个类继承JzvdStd并在XML设置
public class JzvdStdVolumeAfterFullscreen extends JzvdStd {
    public JzvdStdVolumeAfterFullscreen(Context context) {
        super(context);
    }

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

    @Override
    public void onPrepared() {
        super.onPrepared();
        if (screen == SCREEN_FULLSCREEN) {
            mediaInterface.setVolume(1f, 1f);
        } else {
            mediaInterface.setVolume(0f, 0f);
        }
    }

    /**
     * 进入全屏模式的时候关闭静音模式
     */
    @Override
    public void gotoScreenFullscreen() {
        super.gotoScreenFullscreen();
    }

    @Override
    public void setScreenFullscreen() {
        super.setScreenFullscreen();
        if (mediaInterface != null)
            mediaInterface.setVolume(1f, 1f);
    }

    @Override
    public void setScreenNormal() {
        super.setScreenNormal();
        if (mediaInterface != null)
            mediaInterface.setVolume(0f, 0f);
    }
}
复制代码

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

创建一个类继承JzvdStd并在XML设置
public class JzvdStdAutoCompleteAfterFullscreen extends JzvdStd {
    public JzvdStdAutoCompleteAfterFullscreen(Context context) {
        super(context);
    }

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

    @Override
    public void startVideo() {
        if (screen == SCREEN_FULLSCREEN) {
            Log.d(TAG, "startVideo [" + this.hashCode() + "] ");
            JZMediaInterface.SAVED_SURFACE = null;
            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);
//            JZMediaPlayer.instance().positionInList = positionInList;
            onStatePreparing();

        } else {
            super.startVideo();
        }
    }

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

    }
}
复制代码

播放MP3

public class JzvdStdMp3 extends JzvdStd {

    public JzvdStdMp3(Context context) {
        super(context);
    }

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

    @Override
    public int getLayoutId() {
        return R.layout.jz_layout_standard_mp3;
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == cn.jzvd.R.id.thumb &&
                (state == STATE_PLAYING ||
                        state == STATE_PAUSE)) {
            onClickUiToggle();
        } else if (v.getId() == R.id.fullscreen) {

        } else {
            super.onClick(v);
        }
    }

    //changeUiTo 真能能修改ui的方法
    @Override
    public void changeUiToNormal() {
        super.changeUiToNormal();
    }

    @Override
    public void changeUiToPreparing() {
        super.changeUiToPreparing();
    }

    @Override
    public void changeUiToPlayingShow() {
        super.changeUiToPlayingShow();
        thumbImageView.setVisibility(View.VISIBLE);

    }

    @Override
    public void changeUiToPlayingClear() {
        super.changeUiToPlayingClear();
        thumbImageView.setVisibility(View.VISIBLE);
    }

    @Override
    public void changeUiToPauseShow() {
        super.changeUiToPauseShow();
        thumbImageView.setVisibility(View.VISIBLE);
    }

    @Override
    public void changeUiToPauseClear() {
        super.changeUiToPauseClear();
        thumbImageView.setVisibility(View.VISIBLE);
    }

    @Override
    public void changeUiToComplete() {
        super.changeUiToComplete();
    }

    @Override
    public void changeUiToError() {
        super.changeUiToError();
    }
}
复制代码

播放完成不显示预览图

public class JzvdStdShowTextureViewAfterAutoComplete extends JzvdStd {
    public JzvdStdShowTextureViewAfterAutoComplete(Context context) {
        super(context);
    }

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

    @Override
    public void onAutoCompletion() {
        super.onAutoCompletion();
        thumbImageView.setVisibility(View.GONE);
    }

}
复制代码

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

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

    @Override
    protected void onPause() {
        super.onPause();
   //     Jzvd.clearSavedProgress(this, null);
        //home back
        JzvdStd.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]);
        map.put("高清", proxyUrl);
        map.put("标清", VideoConstant.videoUrls[0][6]);
        map.put("普清", VideoConstant.videoUrlList[0]);
        JZDataSource jzDataSource = new JZDataSource(map, "饺子不信");
        jzDataSource.looping = true;
        jzDataSource.currentUrlIndex = 2;
        jzDataSource.headerMap.put("key", "value");//header  这里可以加请求头  mediaplayer
        mJzvdStd.setUp(jzDataSource
                , JzvdStd.SCREEN_NORMAL);
        Glide.with(this).load(VideoConstant.videoThumbList[0]).into(mJzvdStd.thumbImageView);
复制代码

重复播放

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

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

    @Override
    public void onAutoCompletion() {
        super.onAutoCompletion();
        startVideo();   //播放完成开启自动播放 这里选择 startVideo();
    }
}
还有一种方法就是上面清晰度切换loop循环标志
复制代码

重力感应自动进入全屏

    SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    Jzvd.JZAutoFullscreenListener mSensorEventListener = new Jzvd.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);
   }

复制代码

重力感应

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

不保存播放进度

Jzvd.SAVE_PROGRESS = false;
复制代码

取消播放时在非WIFIDialog提示

Jzvd.WIFI_TIP_DIALOG_SHOWED=true;
复制代码

清除某个URL进度

 Jzvd.clearSavedProgress(this, "url");
复制代码

切换播放内核

ijk
    复制Demo中JZMediaIjk类到你的项目下   //记着SO
    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
    jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
                , "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaIjk.class);  //  ijkMediaPlayer
Mediaplayer
     jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
                , "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaSystem.class);
exo
    复制Demo中JZMediaExo类到你的项目下 
    implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
    jzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
                , "饺子快长大", JzvdStd.SCREEN_NORMAL, JZMediaExo.class);  //exo
复制代码

##相关函数回调,屏幕状态,播放器状态,事件 #####继承JzvdStd之后,可以通过父类的mCurrentState,取得当前的播放状态。

  • CURRENT_STATE_IDLE 未知状态,指控件被new出来之后什么都没做
  • CURRENT_STATE_NORMAL 普通状态
  • CURRENT_STATE_PREPARING 视频准备状态
  • CURRENT_STATE_PREPARING_CHANGING_URL 播放中切换url的准备状态
  • CURRENT_STATE_PLAYING 播放中状态
  • CURRENT_STATE_PAUSE 暂停状态
  • CURRENT_STATE_AUTO_COMPLETE 自动播放完成状态
  • CURRENT_STATE_ERROR 错误状态

复写进入播放状态的函数,取得播放状态的回调

  • onStateNormal 进入普通状态,通常指setUp之后
  • onStatePreparing 进入准备中状态,就是loading状态
  • onStatePlaying 进入播放状态
  • onStatePause 进入暂停状态
  • onStateError 进入错误状态
  • onStateAutoComplete 进入自动播放完成状态
了解当前屏幕类型

全屏、小窗、非全屏分别是不同的实例,在继承JzvdStd后,通过mCurrentScreen变量,取得当前屏幕类型

  • SCREEN_WINDOW_NORMAL 普通窗口(进入全屏之前的)
  • SCREEN_WINDOW_LIST 列表窗口(进入全屏之前)
  • SCREEN_WINDOW_FULLSCREEN 全屏
  • SCREEN_WINDOW_TINY 小窗 ####事件
  • 复写onProgress函数,取得每次播放器设置底部seekBar的进度回调
  • 调用changeUrl函数,切换url
  • 复写onClick函数,取得各种按钮的点击事件
  • 复写onTouch函数,取得全屏之后的手势操作

自定义相关 详细请看类说明

/**
 * 事件回调,相关操作,请参考上面的相关函数回调,屏幕状态,播放器状态,事件来,实现你的逻辑
 */
public class cxw extends JzvdStd {
    private Button button;

    public cxw(Context context) {
        super(context);
    }

    public cxw(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    //-----------------------增加某个控件-----------------------------------------//

    @Override
    public int getLayoutId() {
        return R.layout.jz_layout_std;   //复制DEMO下的jz_layout_std(可以重命名,但不能删除控件或修改控件的ID) 增加你想要的控件
    }

    @Override
    public void init(Context context) {
        super.init(context);
        button = findViewById(R.id.button);   //获取添加的控件
        button.setOnClickListener(this);  //给控件设置监听回调  这一步很重要不然没法响应点击事件
        
    }

    @Override
    public void onClick(View v) {
        //这里可以在父类之前获取你想要点击控件之间做的时
        super.onClick(v);
        if (v.getId() == R.id.button) {
            //点击button事件 响应
        }
    }

    //-----------------------UI  修改  显隐---------------------------------------//
    // 比如说 你想在某个状态影藏控件  就复写下面的函数   做显隐
    //  控件查找参考 Jzvd 和JzvdStd 类 找到你想要显隐 的控件实例名
    @Override
    public void changeUiToPlayingShow() {   //这里是播放的时候点击屏幕出现的UI
        super.changeUiToPlayingShow();
    }

    @Override
    public void changeUiToPlayingClear() {   //这里是播放的时候屏幕上面UI消失  只显示下面底部的进度条UI
        super.changeUiToPlayingClear();
    }

    @Override
    public void changeUiToPauseShow() { //这里是暂停的时候屏幕出现的UI
        super.changeUiToPauseShow();
    }

    @Override
    public void changeUiToPauseClear() {  //这里是暂停的时候点击屏幕消失的UI  只显示下面底部的进度条UI
        super.changeUiToPauseClear();
    }

    @Override
    public void changeUiToComplete() {     //这里是播放完成显示的UI
        super.changeUiToComplete();
    }

    @Override
    public void changeUiToError() {    //这里是出错的UI
        super.changeUiToError();
    }

    @Override
    public void changeUiToNormal() {    //这里是Normal  UI
        super.changeUiToNormal();
    }

    @Override
    public void changeUiToPreparing() {     //这里是  Preparing 的UI
        super.changeUiToPreparing();
        loadingProgressBar.setVisibility(GONE);   //这里 我影藏 Preparing 时  加载的圆圈进度
    }

}
复制代码

##常见问题 视频有声音,无画面

  • 开启硬件加速

关于播放直播流,m3u8

  • 是否支持播放取决于播放内核,如果该内核不能播放,请切换内核,或者自己编译Ijk 让他支持。

获取视频某一帧

/**
*  context 上下文
*  uri 视频地址
*  imageView 设置image
*  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);
}
复制代码

视频圆角

ViewOutlineProvider (注:该类是5.0的特性,低于5.0没效果,如果要适配5.0以下这里给出一个思路.9图遮罩)
创建一个类继承ViewOutLineProvider 实现改该方法

public class JzViewOutlineProvider extends ViewOutlineProvider {
    private float mRadius;
    public JzViewOutlineProvider(float radius) {
        this.mRadius = radius;
    }
    @Override
    public void getOutline(View view, Outline outline) {
       Rect rect = new Rect();
       view.getGlobalVisibleRect(rect);
       Rect selfRect = new Rect(0, 0,
             view.getWeight(),view.getHeight());
       outline.setRoundRect(selfRect,mRadius);
    }
}
  mJzvdStd.setOutlineProvider(new JzViewOutlineProvider(radius));
  mJzvdStd.setClipToOutline(true);

复制代码

点击全屏按钮闪退,报错空指针

  • 检查是否正确按照基本使用在manifest中配置。Activity是否继承自AppCompatActivity
 <activity
            android:name=".xxxxxxxActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:screenOrientation="portrait" />
复制代码

视屏宽高不填充屏幕,有黑边

  Jzvd.setTextureViewRotation(90);   //视频旋转90度

   根据自己情况选择一个 填充
  Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_PARENT); 
  Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_FILL_SCROP);   

  Jzvd.setVideoImageDisplayType(Jzvd.VIDEO_IMAGE_DISPLAY_TYPE_ORIGINAL);  //原始大小
复制代码

背景高斯模糊

  • 以module的形式导入项目,在jz_layout_standard.xml 的布局下添加一个Imageview
 <FrameLayout
        android:id="@+id/surface_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <cn.jzvd.ResizableImageView
            android:id="@+id/iv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
这里我为了方便重写了Imageview 使他宽填充屏幕宽,这里怎么简单怎么来想进一切办法让他填充满宽度
复制代码

在JzvdStd类下的init 方法里面获取上面的Imageview控件,好了到此就完了,然后在设置缩略图的下面用能高斯模糊的方法设置就OK,下面是我的做法你可以根据你自己来。

 myJzvdStd.setUp("http://jzvd.nathen.cn/342a5f7ef6124a4a8faf00e738b8bee4/cf6d9db0bd4d41f59d09ea0a81e918fd-5287d2089db37e62345123a1be272f8b.mp4"
                , "饺子快长大", JzvdStd.SCREEN_WINDOW_NORMAL);
        Glide.with(this).load("http://jzvd-pic.nathen.cn/jzvd-pic/1bb2ebbe-140d-4e2e-abd2-9e7e564f71ac.png").into(myJzvdStd.thumbImageView);
        Jzvd.setJzUserAction(new MyUserActionStd());
        Glide.with(ActivityMain.this)
                .load("http://t2.hddhhn.com/uploads/tu/201810/9999/9139710e12.jpg")
                .dontAnimate()
                // 设置高斯模糊
                .bitmapTransform(new BlurTransformation(this, 14, 5))
                .into(myJzvdStd.mFrameLayout);
复制代码

ViewPager翻页视频还在播放

 @Override
    public void onPageSelected(int position) {
        Jzvd.resetAllVideos();
    }
复制代码

视频一直在loading中

  • 检查链接是否是Https或手机版本是否是9.0因为9.0不支持http
  • 是否添加了网络权限
  • 是否该内核支持该视频流
  • 把链接放demo中,看能否播放,如果以上三步没问题不能播放请上github提issuse

转载于:https://juejin.im/post/5cee364e5188251bc6234313

 类似资料: