Android集成IjkPlayer


0x0000 背景

  • 项目需要引入直播功能,而Android原生的VideoView本身是不支持RTMP格式的流媒体播放的。
  • 市面上的开源播放器还是挺好选择的,相比较于IjkPlayer,其他例如Vitamio、VLC的SDK无论使用便利性还是社区的支持都差得远,自己用ffmpeg写成本难以接受。
  • 但是!IjkPlayer在Github上的README文档真心坑,完全按那个文档做连编译都过不了。。

0x0001 致谢

  • 感谢Bilibili工程师的无私开源
  • 本博文参照了:
    Android Studio中如何将ijkplayer 0.6.3导入自己的项目中并使用
    感谢hisonedumobile博主
  • 转载请注明
    作者和平北路
    原文点击链接

0x0002 源码链接

Github:Bilibili/ijkplayer


0x0003 编译

  • 安装homebrew、git、yasm
    非核心内容,请自行百度或谷歌
  • 配置Android SDK、NDK环境变量,在.bash_profile增加如下两行
export ANDROID_SDK=/your/sdk/path
export ANDROID_NDK=/your/ndk/path
  • 下载源码
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.7.8.1
  • 初始化
./init-android.sh
  • 编译ffmpeg
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
  • 编译IjkPlayer
cd ..
./compile-ijk.sh all

到此为止,完成了对源码的编译,ijkplayer-android的目录结构如图


Android集成IjkPlayer_第1张图片
工程结构

0x0004 配置

  • 拷贝gradle文件
    复制/android/ijkplayer/tools文件夹到工程根目录
  • 在工程根目录下的build.gradle文件中增加配置
ext {
    compileSdkVersion = 25
    buildToolsVersion = "25.0.2"
    targetSdkVersion = 25
    versionCode = 700801
    versionName = "0.7.8.1"
}

前三条和你的app module的build.gradle保持一致
后两条和IjkPlayer源码工程中的build.gradle保持一致

  • 依赖关系
    回到刚才我们编译成功的源码目录,如果将/android/ijkplayer作为一个新项目导入Android Studio,运行ijkplayer-example,是可以作为一个独立app run起来的
    我们先把example加入工程:
    File-New-Import Module-/android/ijkplayer/ijkplayer-example
    当然我们希望能把IjkPlayer当做一个第三方库引入,而不是在example工程的基础上实现我们的需求,那么就需要搞清楚各个module的依赖关系:


    Android集成IjkPlayer_第2张图片
    各module依赖关系

    说的直白一点,arm64等5个module一看命名大家就明白是基于不同CPU编译产出的so
    为了简化依赖,我们把这几个module的so文件拷贝到example module下,同时删除这几个module,完成后的example目录结构如图


    Android集成IjkPlayer_第3张图片
    example目录结构
  • 改造example module
    现在的example module是作为application存在的,如果要作为library引入,要处理以下三点


    Android集成IjkPlayer_第4张图片
    调整example build.gradle

    Android集成IjkPlayer_第5张图片
    example增加gradle.properties
  • 加入依赖库
    File-Project Structure-app-Dependencies-添加ijkplayer-example


    Android集成IjkPlayer_第6张图片
    依赖example module

0x0005 开发

IjkVideoView本身继承自FrameLayout,可以和普通的View一样在layout的xml文件中直接加入
对大多数人来说,平时怎么使用VideoView,现在就怎么使用IjkVideoView即可


0x0006 问题

  • 如何让播放器填满IjkVideoView展示
    改造SurfaceRenderView的onMeasure方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    if (this.getWidth() != 0) {
        setMeasuredDimension(this.getWidth(), this.getHeight());
        return;
    }
    int width = getDefaultSize(0, widthMeasureSpec);
    int height = getDefaultSize(0, heightMeasureSpec);
    setMeasuredDimension(width, height);
}
  • 启动之后crash
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

在AndroidManifest.xml中设置Activity的theme属性


    
        
        
    

  • 视频流截图(适用于api14+)
    IjkVideoView改造setRender
public void setRender(int render) {
    switch (render) {
        case RENDER_NONE:
            setRenderView(null);
            break;
        case RENDER_SURFACE_VIEW:
        case RENDER_TEXTURE_VIEW: {
            TextureRenderView renderView = new TextureRenderView(getContext());
            if (mMediaPlayer != null) {
                renderView.getSurfaceHolder().bindToMediaPlayer(mMediaPlayer);
                renderView.setVideoSize(mMediaPlayer.getVideoWidth(), mMediaPlayer.getVideoHeight());
                renderView.setVideoSampleAspectRatio(mMediaPlayer.getVideoSarNum(), mMediaPlayer.getVideoSarDen());
                renderView.setAspectRatio(mCurrentAspectRatio);
            }
            setRenderView(renderView);
            break;
        }
        default:
            Log.e(TAG, String.format(Locale.getDefault(), "invalid render %d\n", render));
            break;
    }
}

增加一个public方法

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public Bitmap getShortcut() {
    if (mRenderView instanceof TextureRenderView) {
        return ((TextureRenderView) mRenderView).getBitmap();
    }
    return null;
}

0x0007 后记

Android播放器的坑太多,慢慢踩,与君共勉

你可能感兴趣的:(Android集成IjkPlayer)