动态加载能力组件 dex & so
最后更新: 2021/2/3动态加载能力组件 dex & so
平台 | 开始支持rom版本 |
豹小秘 | 4.21 |
豹花/大屏 | 4.18 |
豹小秘 Mini | 5.13 |
这项功能可以加载纯业务性的代码和 so,以及基于现有代码的扩展。
这项功能的限制:
- 不能加载带 layout drawable string 等资源的业务代码
- 和原生有代码 和 so 有冲突的,类名和 so 名称不能有冲突
- 新写的 ReactContextBaseJavaModule 中返回的 name 不能和已有的 NativeModules 重名,否则会影响原有功能
- 不能加载需要在 manifest.xml 预埋内容的业务代码
- 不能加载需要使用 assets 资源的功能
生成 dex 和 so
- 首先可以创建一个空的 RN 工程,会自动生成 Android 工程,在 Android 工程中创建 lib module
- 然后在内部实现相应的业务逻辑,并将这些业务逻辑封装为 RN NativeModules 和 ReactPackage
- 业务逻辑实现完成之后,可以执行 gradlew dexRelease 命令,打出 dex 文件(在 libmodule/build/intermediates/dex/release/out 目录下)
- 如果需要引用第三方 jar 库,也需要把第三方库打成 dex 文件,和业务逻辑的 dex 一起,命令如下
dx --dex --output=fastjson.dex ./fastjson-1.2.61.jar
dx 是 android sdk buildtools 里的一个命令行工具,更多使用方式可以查看官网,在 Android/sdk/build-tools/28.0.3/中(也可以是其他版本),需要把这个路径配置系统环境变量中
dex 和 so 放置目录的规则
动态加载的 dex 和 so 要遵循下面的目录存放规则,要放在 opk 的 extraResource/libs/ 下
豹小秘、豹大/花瓶
在豹小秘、豹大/花瓶上需要确定系统运行的 abi ,以及是否为 64 位,然后提供对应的 so 文件。
extraResource
└── libs
├── amap
│ ├── 3dmap-6.6.0.jar
│ ├── config.json
│ ├── dexlib
│ │ ├── amap.dex
│ │ └── amaprnclasses.dex
│ └── jnilib
│ └── libAMapSDK_MAP_v6_6_0.so
└── test
├── config.json
├── dexlib
│ ├── classes1.dex
│ ├── classes2.dex
│ ├── core-3.3.0.dex
│ └── retrofit.dex
└── jnilib
├── libhello-jni.so
└── libplus.so
安装完成之后在 sdcard 上的路径如下
sdcard
└── appid or debug(debug 模式)
└── extra
└── libs
├── amap
│ ├── 3dmap-6.6.0.jar
│ ├── config.json
│ ├── dexlib
│ │ ├── amap.dex
│ │ └── amaprnclasses.dex
│ └── jnilib
│ └── libAMapSDK_MAP_v6_6_0.so
└── test
├── config.json
├── dexlib
│ ├── classes1.dex
│ ├── classes2.dex
│ ├── core-3.3.0.dex
│ └── retrofit.dex
└── jnilib
├── libhello-jni.so
└── libplus.so
jnilib 目录中存放 .so 文件
dexlib 目录中存放 .dex 文件
config.json 中配置 ReactPackge 子类的 classname,如下
{
"packageClassNames": [
"com.ainirobot.testsdk.HelloModuleReactPackage",
"com.ainirobot.testsdk2.Test2ReactPackage"
]
}
豹小秘 Mini 平台
从 豹小秘 Mini 平台 开始支持不同 abi 的 so ,系统会根据当前运行的状态去加载不同的 abi 的so 文件,so 文件放置规则和 Android 项目的 jnilibs 目录一致,如下
extraResource
└── libs
├── testsdk
│ ├── config.json
│ ├── dexlib
│ │ └── classes.dex
│ └── jnilib
│ ├── arm64-v8a
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ ├── armeabi-v7a
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ ├── x86
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ └── x86_64
│ ├── libhello-jni.so
│ └── libjianjian.so
└── testsdk2
├── config.json
└── dexlib
├── fastjson.dex
├── retrofit.dex
└── testsdk2.dex
安装完成之后在 sdcard 上的路径如下
sdcard
└── appid or debug(debug 模式)
└── extra
└── libs
├── testsdk
│ ├── config.json
│ ├── dexlib
│ │ └── classes.dex
│ └── jnilib
│ ├── arm64-v8a
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ ├── armeabi-v7a
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ ├── x86
│ │ ├── libhello-jni.so
│ │ └── libjianjian.so
│ └── x86_64
│ ├── libhello-jni.so
│ └── libjianjian.so
└── testsdk2
├── config.json
└── dexlib
├── fastjson.dex
├── retrofit.dex
└── testsdk2.dex
这样 dex 和 so 就可以在 opk 运行的时候被动态 load 起来。
接下来只需要在 RN 工程的业务代码中,直接使用封装的 NativeModules ,又或者是你用的是一个第三方库,那需要在 package.json 中加上这个库的依赖。
import { NativeModules } from 'react-native';
const Hello = NativeModules.Hello;
const Test2 = NativeModules.Test2;
export class HelloUtil {
public static getStringFromJNI() {
return Hello && Hello.getStringFromJNI();
}
public static getStringFromKT() {
return Hello && Hello.getStringFromKT();
}
public static jianjian(num: number) {
return Hello && Hello.jianjian(num);
}
public static far() {
return Test2 && Test2.far();
}
}
Debug 模式
debug 模式需要把 libs 目录 push 进 /sdcard/debug/extra/ 下
示例:
豹小秘、豹大/花瓶参考 DEMO
豹小秘 Mini 平台参考 DEMO