乐趣区

关于android:Android-视频播放器第三方框架之ijkplayer

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 库

看到咱们是在 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…

结尾:不要伪装致力,后果不会陪你演戏

退出移动版