You need to enable JavaScript to run this app.
导航
下发so减少包大小示例说明
最近更新时间:2025.03.18 12:29:11首次发布时间:2025.03.18 12:29:11
我的收藏
有用
有用
无用
无用
下发so减少包大小的说明

为了减少包体增量,自版本V4.4.2后,sample代码中带有下发so逻辑,接入形式发生变化

前置准备
  1. 解压aar文件,拿到jar包与so
  2. jar包需放置在library_core/lib目录下,或者在gradle中的自己放库的目录下
  3. 使用何种架构的so文件,由业务方自行决定
注意事项

安卓端加载sdk方式

通过aar加载
需要在创建licenseWrapper对象前调用 BytedLicenseWrapper.loadLib()
通过so加载
需要在创建licenseWrapper对象前,利用System.load()传入so库所在路径来加载sdk
示例代码

try {
    BytedLicenseWrapper.loadLib();
} catch (UnsatisfiedLinkError e) {
    ExternalLibraryLoader externalLibraryLoader = new ExternalLibraryLoader(new SdCardLibrarySource(mContext));
    externalLibraryLoader.loadLib();
}
this.licenseWrapper = new com.bytedance.labcv.licenselibrary.BytedLicenseWrapper(parames, this.httpProvider);

详情可见加载SDK的Step2章节。

关于下发so的几项说明

  1. 下发so的目的是为了减少包大小,但并不是安装好app之后就能使用,需要注意一定确保so文件均下载到本地后,功能才可以使用;如果so文件未下发,会造成app打开后功能无效等问题。
  2. 不提供下发的服务,下发服务需要业务方自己实现。

so下发在sample中的体现

sample通过将so库放置在sdcard存储中来模拟下发过程以及加载sdk的过程,不提供线上下发环境。
注意
版本4.4.2开始,安卓端sdk加载方式发生变更。如果通过aar加载sdk,无需额外操作;如果通过so来加载sdk,则需要在调用任何sdk相关接口,包括鉴权和创建renderManager对象前,利用System.load()传入so库所在路径来加载sdk,demo中通过USE_SO_LIB开关来控制是否启用该加载方式。实例代码如下:

if (USE_SO_LIB) {
    ExternalLibraryLoader externalLibraryLoader = new ExternalLibraryLoader(new SdCardLibrarySource(context));
    externalLibraryLoader.loadLib();
}
  1. 将library_core/libs路径下的effectAAR-release.aar删除,替换为解压获得的jar包,文件结构如下:
    Image
  2. 将指定架构的so库通过adb push的方式放到sdcard的根目录下。
    注:sample中需要push到根目录下,实际接入时可以参考SdCardLibrarySource.java部分代码,更改为自己的目录
  3. Android Studio中,build完工程并直接在手机上安装demo后,会因为没有读写磁盘权限无法加载sdk而崩溃,需要在设置中添加磁盘读写权限,即可正常运行demo
下发使用方式

Step 1 将so文件下发并确保所有so文件存放在指定目录

  1. 每个架构下面有2个so文件
    Image
  2. so文件下载之后,需存放于内部存储私有目录下面。我们内部测试时存放的目录是/data/data/<package/application id>/files/external_libs,该目录可以通过Context.getFilesDir() 获取。

Step 2 定义实现外部库加载类

实现so库的顺序加载。
示例代码如下:

package com.bytedance.labcv.core.external_lib;

import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ExternalLibraryLoader {
    static String TAG = "ExternalLibraryLoader";

    static private ArrayList<String> loadedLibraryNames = new ArrayList<>();

    public ExternalLibraryLoader() {
    }
    
    public void loadLib() {
        List<String> list = Arrays.asList("c++_shared", "effect");
        if (!onLoadNativeLibs(list)) {
            Log.e(TAG, "dynamically load library failed!");
        }
    }

    public boolean onLoadNativeLibs(List<String> list) {
        for (int i = 0; i < list.size(); i++) {
            if (!load(list.get(i))) {
                return false;
            }
        }
        return true;
    }

    private boolean load(String libraryName) {
        if (loadedLibraryNames.contains(libraryName)) {
            return true;
        }
        try {
            String targetLibraryName = String.format(Locale.US, "lib%s.so", libraryName);
            File soFile = new File(ApplicationSingleton.application.getFilesDir().getAbsolutePath()
                    + File.separator + "external_libs/jni/arm64-v8a/" + targetLibraryName);
            if (soFile.exists()) {
                System.load(soFile.getAbsolutePath());
            }
            loadedLibraryNames.add(libraryName);
            return true;
        } catch (UnsatisfiedLinkError e) {
            e.printStackTrace();
            return false;
        } finally {
        }
    }
}

Step 3 调用CV SDK接口

  1. 确保所有需要的so文件都存放在指定目录下面。
  2. libc++shared.so需要在libeffect.so前load。
  3. 按照接口说明文档来调用CV SDK接口。