LiteAVSDK集成,动态加载so库

一、简介

安卓开发中使用Android studio集成三方SDK(比如腾讯视频云移动直播、播放器、短视频、实时音视频),通常有两种集成方式:aar集成、jar+so集成。安卓集成已经很成熟了,详见SDK集成指引

二、动态加载so

随着项目业务越来越多,对APK 体积大小要求尽可能的瘦身,通常可以考虑采用在线加载的方式减少最终 apk 安装包的大小。

以移动直播5.4全功能专业版(LiteAVSDK_Professional_Android_5.4.6097)为例,整个 SDK 的体积主要来自于 so 文件,这些 so 文件是 SDK 正常运行所依赖的音视频编解码库、图像处理库 以及 声学处理组件。各个 so 库的具体作用,可以阅读 库说明

具体改造如下:

  1. 使用 jar + so 方式集成,到官网下载 SDK,解压 LiteAVSDK_xxx.zip 压缩包后得到 libs 目录,里面主要包含 so 文件和 jar 文件。
  2. 上传 SO 文件 将 SDK 压缩包中的 so 文件上传到 CDN,并记录下载地址,比如 http://xxx.com/so_files.zip。
  3. 启动准备 在用户启动 SDK 相关功能前,比如开始播放视频之前,先用 loading 动画提示用户“正在加载相关的功能模块”。
  4. 下载 SO 文件 在用户等待过程中,APP 就可以到 http://xxx.com/so_files.zip 下载 so 文件,并存入应用目录下(比如应用根目录下的 files 文件夹),为了确保这个过程不受运营商 DNS 拦截的影响,请在文件下载完成后校验 so 文件的完整性。
  5. 加载 SO 文件 等待所有 so 文件就位以后,调用 TXLiveBase 的 setLibraryPath 将下载的目标 path 设置给 SDK, 然后再调用 SDK 的相关功能。之后,SDK 会到这些路径下加载需要的 so 文件并启动相关功能。

二、示例demo

1、工具类的写法。

下载、解压、校验完整性的过程,由客户自己灵活完成,demo就不给出演示了。我们直接从复制到内部存储开始

//FileUtils类
public static boolean copyFolder (String oldPath , String newPath){

    File newFile = new File(newPath);

    if(!newFile.exists()){
        if(!newFile.mkdirs()){
            Log.e("TAG","无法创建路径");
            return  false;
        }
    }

    File oldFile = new File(oldPath);

    String[] files = oldFile.list();

    Log.i("TAG", "files.length: "+files.length);

    File temp;

    for(String file : files){
        if(oldPath.endsWith(File.separator)){
            temp = new File(oldFile + file);
        }else{
            temp = new File(oldPath + File.separator + file);
        }
        if(temp.isDirectory()){
            copyFolder(oldPath + "/"+file , newPath + "/" + file);
        }else if(!temp.exists()){
            Log.e("TAG", "copyFolder: oldFile not exist");
            return  false;
        }else if(!temp.isFile()){
            Log.e("TAG", "copyFolder: oldFile not file");
            return  false;
        }else if(!temp.canRead()){
            Log.e("TAG", "copyFolder: oldFile cannot read");
            return false;
        }else{
            try {
                FileInputStream fileInputStream = new FileInputStream(temp);
                FileOutputStream fileOutputStream = new FileOutputStream(newPath + "/" +temp.getName());
                byte[] buffer = new byte[1024];
                int byteRead;
                while ((byteRead = fileInputStream.read(buffer))!=-1){
                    fileOutputStream.write(buffer,0,byteRead);
                }
                fileInputStream.close();
                fileOutputStream.flush();
                fileOutputStream.close();

            } catch (Exception e) {
                e.printStackTrace();
            }

            File fileile = new File(newPath + "/" +temp.getName());
            fileile.setWritable(true);
            fileile.setReadable(true);
            fileile.setExecutable(true);
        }

    }
    return  true ;
}

2、调用setLibraryPath开始动态加载so

//下载so的外部存储目录,比如sd卡下的armeabi文件夹
oldFilePath = Environment.getExternalStorageDirectory().getPath()+"/armeabi";

//应用的根目录file文件下新建armeabi文件夹
newFilePath = getFilesDir().getAbsolutePath()+"/armeabi";

//复制到内存存储
FileUtils.copyFolder(oldFilePath, newFilePath)

//sdk接口动态加载so
TXLiveBase.setLibraryPath(newFilePath);

3、验证

//设置在 Android Studio 的控制台打印 SDK 的相关输出。
TXLiveBase.setConsoleEnabled(true);

//获取sdk版本号
String sdkVersionStr = TXLiveBase.getSDKVersionStr();
Log.i("TAG", "sdkVersionStr: "+sdkVersionStr);

//开始推流
mLivePusher.startPusher(rtmpUrl.trim());

正常情况下可以推流成功,如上图。踩到坑的话会遇到如下crash,请重新检查集成配置。

至此算是全部完成了。

三、商业版动态加载so

商用企业版相较于专业版,增加了大眼、瘦脸、动效贴纸、绿幕等特效功能,是基于优图实验室的人脸识别技术和天天P图的美妆技术为基础开发的特权功能,腾讯云小直播团队通过跟优图和P图团队合作,将这些特效深度整合到 LiteAVSDK 的图像处理流程中,以实现更好的视频特效。

如果是集成的商业版SDK,比如移动直播5.4商业版(LiteAVSDK_Enterprise_Android_5.4.6097),解压sdk包,会发现多了一些jar、so库,而这些so库的动态加载方式,优图实验室有如下特殊加载要求。

1、这三个so库必需要在本地加载。

2、这些so库需要按照如下顺序动态加载。

//sdk接口动态加载so
TXLiveBase.setLibraryPath(newFilePath);
//系统接口动态加载so
loadLibrary(newFilePath, "YTCommon");
loadLibrary(newFilePath, "image_filter_common");
loadLibrary(newFilePath, "image_filter_gpu");
loadLibrary(newFilePath, "algo_rithm_jni");
loadLibrary(newFilePath, "format_convert");
loadLibrary(newFilePath, "ParticleSystem");

loadLibrary(newFilePath,"nnpack");
loadLibrary(newFilePath, "YTHandDetector");
loadLibrary(newFilePath, "GestureDetectJni");

loadLibrary(newFilePath,"YTIllumination");
loadLibrary(newFilePath,"YTFaceTrackPro");
loadLibrary(newFilePath,"algo_youtu_jni");


 private static boolean loadLibrary(String path, String name) {
        boolean loadSucess = false;
        try {
            if (!TextUtils.isEmpty(path)) {
                String libName = path+"/lib"+name+".so";

                File file = new File(libName);
                if (file.exists()) {
                    Log.i("TAG", libName + " exist, " + file.length());
                }
                else {
                    Log.i("TAG", libName + " not exist");
                }

                file.setExecutable(true);
                file.setReadable(true);
                file.setWritable(true);

                System.load(libName);
                loadSucess = true;
            }
        } catch (Error e1) {
            Log.i("NativeLoad","load library : "+e1.toString());
        } catch (Exception e) {
            Log.i("NativeLoad","load library : "+e.toString());
        }
        return loadSucess;
    }

3、验证动效功能

//设置动效Licence
TXLiveBase.getInstance().setLicence(context, LicenceUrl, Key);
//验证Licence
TXLiveBase.getInstance().getLicenceInfo(context);
//设置推流动效
mLivePusher.setMotionTmpl(params.mMotionTmplPath);

正常情况下可以打开动效,如上图。踩到坑的话会遇到如下crash,请重新检查集成配置。

四、相关知识

1、目前几种 Android CPU ABI

CPU 架构

描述

armeabi

第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢

armeabi-v7a

第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能

arm64-v8a

第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit

x86

intel 32位,一般用于平板

x86_64

intel 64位,一般用于平板

mips

少接触

mips64

少接触

2、设置 APK 的对应支持

//非商业版,6.3之前的版本支持armeabi、armeabi-v7a,6.3开始支持armeabi、armeabi-v7a、arm64-v8a
//商业版,只支持armeabi
defaultConfig {
    ndk {
        abiFilters "armeabi"//,"armeabi-v7a","arm64-v8a","x86_64"
    }
}

3、查看 手机CPU ABI

4、Zygote相关知识

  • 所有的App在运行时,都是由Zygote进程创建VM再运行的。
  • 一般设备只支持32位系统,但现在的新设备都已经支持64位(同时兼容32位)。对于这些新设备来说,有两个Zytgote(一个32位,一个64位)进程同时运行。

所以当App运行在64位系统上,又区分以下三种情况: 

  • 如果App只包含64位的so库,则它将运行在一个64位的进程中,即VM是由Zytgote 64创建的。
  • 如果App包含32位的so库,则它将运行在一个32位的进程中,即VM是由Zytgote创建的。
  • 如果App不包含任何so库,则它将默认运行在64位的进程中。

所以当你的工程只指定支持armeabi,而运行在64位手机上动态加载so,会出现闪退。解决办法就是:先把一个32位的so文件打进安装包,其它so库在运行时动态加载,这样App启动的是32位进程,动态加载的so库也是32位版本,运行时就不再闪退。

五、资源

相关文章:动态加载so库的实现方法与问题处理

Android 的 so 文件加载机制提问源码总结参考资料

demo下载

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券