Android 视频播放器第三方框架之ijkplayer

一:介绍
ijkplayer是b站开源的超级好用的视频播放器喔,相信大家都早有耳闻。ijkplayer Android和ios都可用,还支持多种视频的硬解码
二:使用
第一步:添加依赖

dependencies {
//一般这2个已经足够用了,这是添加了一个armv7a的cpu架构,支持armv7a和arm64覆盖了大部分手机
 //required, enough for most devices.
    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'

    // Other ABIs: optional
    //这里x86 x86_64针对平板和模拟器
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
    implementation 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
    implementation 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
    implementation 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'

    //ExoPlayer as IMediaPlayer: optional, experimental
    implementation 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
    
    }

第二步:添加3个so库
image.png
看到我们是在libs下配置的·so库
需要app在build.gradle下

android{
defaultConfig{
 ndk {
            //选择要添加的对应cpu类型的.so库。,打包编译只会加重一个armeabi-v7a,so库
            abiFilters 'armeabi-v7a'
        }
        }
        
        //应为在libs下配置的需要定位到,如果是在src/main创建jniLibs文件夹就需要下面
        sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
        }

三个so库libijkffmpeg.so封装解码的使用,libijkplayer.so视频播放的,libijksdl.so
第三步:创建一个View

public class MyIjkVideoView extends FrameLayout {

    private Context mContext;//上下文
    private IMediaPlayer mMediaPlayer = null;//视屏播放
    private TextView subtitleDisplay;//字幕View
    private SurfaceView surfaceView;//视图主要适用于被动更新,例如频繁地刷新

    private VideoPlayerListener listener;//jiant

    /**
     * 视频文件地址
     */
    private String mPath = "";

    private boolean mEnableBackgroundPlay = false;//是否开启后台服务

    public MyIjkVideoView(@NonNull Context context) {
        super(context);
        initVideoView(context);
    }

    public MyIjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initVideoView(context);
    }

    public MyIjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initVideoView(context);
    }

    /**
     * 初始化VideoView
     */
    private void initVideoView(Context context) {
        mContext = context;

        //是否开启后台播放,如果开启了后台播放,就启动一个Service来做后台播放。
        initBackground();
        //初始化渲染器,创建SurfaceView或TextureView,并addView()。(IjkVideoView是FrameLayout)
        initRenders();

        //焦点
        setFocusable(true);
        setFocusableInTouchMode(true);
        requestFocus();

        //字幕View
        subtitleDisplay = new TextView(context);
        subtitleDisplay.setTextSize(24);
        subtitleDisplay.setGravity(Gravity.CENTER);
        FrameLayout.LayoutParams layoutParams_txt = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.WRAP_CONTENT,
                Gravity.BOTTOM);
        addView(subtitleDisplay, layoutParams_txt);

    }

    private void initRenders() {

    }

    private void initBackground() {
        //这里相当于没有进去,具体需要再处理
        if (mEnableBackgroundPlay) {
            MediaPlayerService.intentToStart(getContext());
            mMediaPlayer = MediaPlayerService.getMediaPlayer();
        }

    }

    /**
     * 设置视频地址。
     * 根据是否第一次播放视频,做不同的操作。
     *
     * @param path the path of the video.
     */
    public void setVideoPath(String path) {
        if (TextUtils.equals("", mPath)) {
            //如果是第一次播放视频,那就创建一个新的surfaceView
            mPath = path;
            createSurfaceView();
        } else {
            //否则就直接load
            mPath = path;
            load();
        }
    }

    /**
     * 新建一个SurfaceView
     */

    private void createSurfaceView() {
        //生成一个新的surface view
        surfaceView = new SurfaceView(mContext);
        surfaceView.getHolder().addCallback(new LmnSurfaceCallback());
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT
                , LayoutParams.MATCH_PARENT, Gravity.CENTER);
        surfaceView.setLayoutParams(layoutParams);
        this.addView(surfaceView);
    }

    /**
     * surfaceView的监听器,内部类
     */
    private class LmnSurfaceCallback implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(@NonNull SurfaceHolder holder) {
            //在SurfaceView创建
        }

        @Override
        public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
            //在SurfaceView改变,加载视屏
            load();

        }

        @Override
        public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
            //在SurfaceView销毁

        }
    }

    /**
     * 加载视屏
     */
    private void load() {
        //每次都要重新创建IMediaPlayer
        createPlayer();
        try {
            mMediaPlayer.setDataSource(mPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //给mediaPlayer设置视图
        mMediaPlayer.setDisplay(surfaceView.getHolder());

        mMediaPlayer.prepareAsync();
    }

    private void createPlayer() {
        //去除旧的
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.setDisplay(null);
            mMediaPlayer.release();
        }

        //新建一个新的
        IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
        ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);
        //开启硬解码        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
        mMediaPlayer = ijkMediaPlayer;


        if (listener != null) {
            mMediaPlayer.setOnPreparedListener(listener);
            mMediaPlayer.setOnErrorListener(listener);
            mMediaPlayer.setOnCompletionListener(listener);
        }
    }

    public void setListener(VideoPlayerListener listener) {
        this.listener = listener;
        if (mMediaPlayer != null) {
            mMediaPlayer.setOnPreparedListener(listener);
        }
    }




    public interface VideoPlayerListener extends IMediaPlayer.OnPreparedListener,
            IMediaPlayer.OnCompletionListener,
            IMediaPlayer.OnErrorListener {
    }

    /**下面配置一些暂停,开始,停止等方法*/
    public boolean isPlaying() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.isPlaying();
        }
        return false;
    }

    public void start() {
        if (mMediaPlayer != null) {
            mMediaPlayer.start();
        }
    }

    public void pause() {
        if (mMediaPlayer != null) {
            mMediaPlayer.pause();
        }
    }

    public void stop() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
        }
    }

    public void reset() {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
        }
    }

    public void release() {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

}

在布局中使用View

<com.ruan.mygitignore.MyIjkVideoView
        android:id="@+id/ijk_video"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

第四步:调用

MyIjkVideoView ijkVideoView=findViewById(R.id.ijk_video);
        String url = "https://wdl.wallstreetcn.com/41aae4d2-390a-48ff-9230-ee865552e72d";
        //加载本地库
        IjkMediaPlayer.loadLibrariesOnce(null);
      IjkMediaPlayer.native_profileBegin("libijkplayer.so");
      //监听
        ijkVideoView.setListener( new MyIjkVideoView.VideoPlayerListener() {
            @Override
            public void onCompletion(IMediaPlayer iMediaPlayer) {
                Log.d("aa","完成");

            }

            @Override
            public boolean onError(IMediaPlayer iMediaPlayer, int i, int i1) {
                Log.d("aa","失败");
                return false;
            }

            @Override
            public void onPrepared(IMediaPlayer iMediaPlayer) {
                Log.d("aa","准备");

            }
        });
        //设置路径
    ijkVideoView.setVideoPath(url);
    //开始加载
    ijkVideoView.start();
    
    

下面是一个gitHub上官方的例子
https://github.com/Bilibili/i...

结尾:不要假装努力,结果不会陪你演戏


Rocky_ruan
57 声望5 粉丝

不积跬步,无以至千里