您当前的位置: 首页 >  ide

Kevin-Dev

暂无认证

  • 1浏览

    0关注

    544博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Android -- 开源库】JZVideo 的基本使用

Kevin-Dev 发布时间:2017-08-14 11:49:30 ,浏览量:1

在这里插入图片描述

一、简介

高度自定义的安卓视频框架 MediaPlayer exoplayer ijkplayer ffmpeg

目前最新的版本是 7.7.0。 GitHub:JZVideo 中文文档:JZVD文档

特点
  • 可以完全自定义UI和任何功能。
  • 很容易切换播放引擎,支持的视频格式和协议取决于播放引擎,android.media.MediaPlayer或者ijkplayer等。
  • 可以检测列表的滑动。
  • 可以嵌入到多个控件中,比如ListView、Fragment,RecyclerView等等,多重嵌套也可以。
  • 可以实现全屏播放和小窗播放。
  • 可以在加载、暂停和播放等状态下切换全屏和退出全屏。
  • 可以进行屏幕适配,铺满全屏或者全屏裁剪。
  • 好像还支持重力感应自动横屏。
  • 全屏后可以用手势修改进度和音量。
  • Home键退出界面暂停播放,返回界面的时候继续播放。
二、框架引入

1. 在 app/build.gradle 中添加如下依赖:

implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'

2. 在清单文件中添加网络权限:

	
    
三、播放在线视频

1. 效果图 01.png

2. 使用 1). 布局中添加如下控件

    

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

public class MainActivity extends BaseActivity {
    private String videoUrl = "https://v-cdn.zjol.com.cn/280443.mp4";
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        initView();
    }

    private void initView() {
        JzvdStd videoPlayer = findViewById(R.id.jz_video);
        videoPlayer.setUp(videoUrl,"追龙");
        videoPlayer.posterImageView.setImageResource(R.mipmap.ic_cover);
//        videoPlayer.startVideo();
    }

    @Override
    public void onBackPressed() {
        if (Jzvd.backPress()) {
            return;
        }
        super.onBackPressed();
    }
    @Override
    protected void onPause() {
        super.onPause();
        Jzvd.releaseAllVideos();
    }
}
四、播放本地视频

1. 效果图 在这里插入图片描述 2. 准备本地小视频 在这里插入图片描述

3. JzvdStdAssert.java

/**
 * Created on 2022/3/10 14:51
 *
 * @author Gong Youqiang
 */
public class JzvdStdAssert extends JzvdStd {
    public JzvdStdAssert(Context context) {
        super(context);
    }

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


    @Override
    public void onPrepared() {
        state = STATE_PREPARED;
        if (!preloading) {
            mediaInterface.start();
            preloading = false;
        }
        onStatePlaying();
    }
}

4. 布局文件




    

    


    
        

        
            

            
        

    


5. JZMediaSystemAssertFolder.java

/**
 * Created on 2022/3/10 11:39
 *
 * @author Gong Youqiang
 */
public class JZMediaSystemAssertFolder extends JZMediaInterface implements
        MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
        MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnSeekCompleteListener,
        MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener,
        MediaPlayer.OnVideoSizeChangedListener {

    public MediaPlayer mediaPlayer;

    public JZMediaSystemAssertFolder(Jzvd jzvd) {
        super(jzvd);
    }

    @Override
    public void prepare() {
        release();
        mMediaHandlerThread = new HandlerThread("JZVD");
        mMediaHandlerThread.start();
        mMediaHandler = new Handler(mMediaHandlerThread.getLooper());//主线程还是非主线程,就在这里
        handler = new Handler();

        mMediaHandler.post(() -> {
            try {
                mediaPlayer = new MediaPlayer();
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.setLooping(jzvd.jzDataSource.looping);
                mediaPlayer.setOnPreparedListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setOnCompletionListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setOnBufferingUpdateListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setScreenOnWhilePlaying(true);
                mediaPlayer.setOnSeekCompleteListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setOnErrorListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setOnInfoListener(JZMediaSystemAssertFolder.this);
                mediaPlayer.setOnVideoSizeChangedListener(JZMediaSystemAssertFolder.this);

                //two lines are different
                AssetFileDescriptor assetFileDescriptor = jzvd.getContext().getAssets().openFd(jzvd.jzDataSource.getCurrentUrl().toString());
                mediaPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());

                mediaPlayer.prepareAsync();
                mediaPlayer.setSurface(new Surface(jzvd.textureView.getSurfaceTexture()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    @Override
    public void start() {
        mMediaHandler.post(() -> mediaPlayer.start());
    }

    @Override
    public void pause() {
        mMediaHandler.post(() -> mediaPlayer.pause());
    }

    @Override
    public boolean isPlaying() {
        return mediaPlayer.isPlaying();
    }

    @Override
    public void seekTo(long time) {
        mMediaHandler.post(() -> {
            try {
                mediaPlayer.seekTo((int) time);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        });
    }

    @Override
    public void release() {
        if (mMediaHandler != null && mMediaHandlerThread != null && mediaPlayer != null) {//不知道有没有妖孽
            HandlerThread tmpHandlerThread = mMediaHandlerThread;
            MediaPlayer tmpMediaPlayer = mediaPlayer;
            JZMediaInterface.SAVED_SURFACE = null;

            mMediaHandler.post(() -> {
                tmpMediaPlayer.release();//release就不能放到主线程里,界面会卡顿
                tmpHandlerThread.quit();
            });
            mediaPlayer = null;
        }
    }
    
    @Override
    public long getCurrentPosition() {
        if (mediaPlayer != null) {
            return mediaPlayer.getCurrentPosition();
        } else {
            return 0;
        }
    }

    @Override
    public long getDuration() {
        if (mediaPlayer != null) {
            return mediaPlayer.getDuration();
        } else {
            return 0;
        }
    }

    @Override
    public void setVolume(float leftVolume, float rightVolume) {
        if (mMediaHandler == null) return;
        mMediaHandler.post(() -> {
            if (mediaPlayer != null) mediaPlayer.setVolume(leftVolume, rightVolume);
        });
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void setSpeed(float speed) {
        PlaybackParams pp = mediaPlayer.getPlaybackParams();
        pp.setSpeed(speed);
        mediaPlayer.setPlaybackParams(pp);
    }

    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        handler.post(() -> jzvd.onPrepared());//如果是mp3音频,走这里
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        handler.post(() -> jzvd.onCompletion());
    }

    @Override
    public void onBufferingUpdate(MediaPlayer mediaPlayer, final int percent) {
        handler.post(() -> jzvd.setBufferProgress(percent));
    }

    @Override
    public void onSeekComplete(MediaPlayer mediaPlayer) {
        handler.post(() -> jzvd.onSeekComplete());
    }

    @Override
    public boolean onError(MediaPlayer mediaPlayer, final int what, final int extra) {
        handler.post(() -> jzvd.onError(what, extra));
        return true;
    }

    @Override
    public boolean onInfo(MediaPlayer mediaPlayer, final int what, final int extra) {
        handler.post(() -> {
            if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
                if (jzvd.state == Jzvd.STATE_PREPARING
                        || jzvd.state == Jzvd.STATE_PREPARING_CHANGE_URL) {
                    jzvd.onPrepared();
                }
            } else {
                jzvd.onInfo(what, extra);
            }
        });
        return false;
    }

    @Override
    public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
        handler.post(() -> jzvd.onVideoSizeChanged(width, height));
    }

    @Override
    public void setSurface(Surface surface) {
        mediaPlayer.setSurface(surface);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.i("GD", "======= onSurfaceTextureAvailable =======");
        if (SAVED_SURFACE == null) {
            SAVED_SURFACE = surface;
            prepare();
        } else {
            jzvd.textureView.setSurfaceTexture(SAVED_SURFACE);
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }
}

6. VideoActivity.java

public class VideoActivity extends BaseActivity {
    @BindView(R.id.title_bar)
    TitleBar mTitleBar;

    @BindView(R.id.jz_video)
    JzvdStdAssert mJzVideo;

    public String localVideoPath;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_video;
    }

    @Override
    protected void initView() {
        mTitleBar.setOnTitleBarListener(new OnTitleBarListener() {
            @Override
            public void onLeftClick(View view) {
                finish();
            }

            @Override
            public void onTitleClick(View view) {

            }

            @Override
            public void onRightClick(View view) {

            }
        });

        localVideoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/DCIM/Camera/activity_local_video.mp4";

        //checkPermission
        int permission = ActivityCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE");
        if (permission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    "android.permission.READ_EXTERNAL_STORAGE",
                    "android.permission.WRITE_EXTERNAL_STORAGE"}, 1);
        }

        //cp video 防止视频被意外删除
        cpAssertVideoToLocalPath();

        mJzVideo.setUp("local_video.mp4", "4K视频", JzvdStd.SCREEN_NORMAL, JZMediaSystemAssertFolder.class);
        mJzVideo.posterImageView.setImageResource(R.mipmap.ic_cover);

    }

    @OnClick({R.id.iv_machine_no,R.id.iv_machine_ok})
    public void clicked(View view) {
        switch (view.getId()) {
            case R.id.iv_machine_no:
                MessageBean messageBean = new MessageBean();
                messageBean.setItemNum(5);
                messageBean.setStatus(500);
                EventBus.getDefault().post(messageBean);
                readyGo(MainActivity.class);
                finish();
                break;

            case R.id.iv_machine_ok:
                MessageBean message = new MessageBean();
                message.setItemNum(5);
                message.setStatus(200);
                EventBus.getDefault().post(message);
                readyGo(MainActivity.class);
                finish();
                break;

            default:
                break;
        }
    }

    public void cpAssertVideoToLocalPath() {
        if (new File(localVideoPath).exists()) return;

        try {
            InputStream myInput;
            OutputStream myOutput = new FileOutputStream(localVideoPath);
            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();
            Toast.makeText(this, "cp from assert to local path succ", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onBackPressed() {
        if (Jzvd.backPress()) {
            return;
        }
        super.onBackPressed();
    }
    @Override
    protected void onPause() {
        super.onPause();
        JZUtils.clearSavedProgress(this, null);
        Jzvd.releaseAllVideos();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                cpAssertVideoToLocalPath();
            } else {
                finish();
            }
        }
    }
}
五、播放本地音频

1. 效果图 在这里插入图片描述

2. JzvdStdMp3.java

/**
 * Created on 2022/3/14 14:56
 *
 * @author Gong Youqiang
 */
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_mp3;
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == cn.jzvd.R.id.poster &&
                (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();
        posterImageView.setVisibility(View.VISIBLE);

    }

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

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

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

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

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

3. jz_layout_mp3.xml




    

    


    

    

        

        

        

        

        
    

    

    

    

        

        

        

            

            
        
    

    

    

        
    


    

    

        

        
    

4. 使用

public class MachineActivity extends BaseActivity{

    @BindView(R.id.title_bar)
    TitleBar mTitleBar;

    @BindView(R.id.jz_mp3)
    JzvdStdMp3 mStdMp3;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_machine;
    }

    @Override
    protected void initView() {
        mTitleBar.setOnTitleBarListener(new OnTitleBarListener() {
            @Override
            public void onLeftClick(View view) {
                finish();
            }

            @Override
            public void onTitleClick(View view) {

            }

            @Override
            public void onRightClick(View view) {

            }
        });

        mStdMp3.setUp("machine.mp3", "机震测试", JzvdStd.SCREEN_NORMAL,JZMediaSystemAssertFolder.class);
        mStdMp3.posterImageView.setImageResource(R.mipmap.ic_machine_thump);
    }

   
    @Override
    public void onBackPressed() {
        if (Jzvd.backPress()) {
            return;
        }
        super.onBackPressed();
    }
    @Override
    protected void onPause() {
        super.onPause();
        JZUtils.clearSavedProgress(this, null);
        Jzvd.releaseAllVideos();
    }

}
关注
打赏
1658837700
查看更多评论
立即登录/注册

微信扫码登录

0.0688s