Android项目接入Rust
背景
本次讨论在已有的安卓项目工程中配置rust的方法,同时记录一下踩坑过程,首先本地pc端配置好rust的开发环境,配置rust的过程就默认你会了。
项目配置
项目结构
在已有的项目,我们推荐新建一个module,这里不需要native module,就是普通的java module。

image.png
我们把rust工程可以放到module平级目录,或module下面都是可以的。

image.png
我们把所有rust相关的代码,全部放到rustsdk工程目录,可以单独打开,单独成仓库,单独维护。和这个rust相关的桥接层,我们全部放在本地的java module里面。
项目根grade配置
主要的思路是参考https://github.com/mozilla/rust-android-gradle
现在项目的跟目录下配置rust-android-gradle,具体的版本,可以参考github上最新的
1 | buildscript { |
module gradle配置
先给模块添加插件,
然后主要的就是配置cargo这个dsl,具体的参数表意可以在github上面看 image.png
需要主要的是,modlue 直到 sdk的目录,包含Cargo.toml的位置,libname需要和Cargo.toml文件里面指定的一致,其它按需配置即可。
按需要添加交叉编译器
1 | rustup target add armv7-linux-androideabi # for arm |
可选,每次编译的时候,触发一次rust的编译
1 | tasks.configureEach { task -> |
或者项目目录下,手动
上面基本安卓项目里面就配置完了。下面展示一个调用示例, java调一下rust。
1 | package com.example.mylibrary; |
Rust SDK配置
Cargo.toml配置
1 | [package] |
lib.rs
1 | extern crate jni; |
然后,在Android Studio里面编译app调用这个方法就ok了。这里会有目标so,可以用检查一下导出函数。 image.png
我没有直接把所有依赖放到 [target.’cfg(target_os = “android”)’.dependencies]下,是因为这样在pc端可以直接编译,检查错误,利于开发。
比起👇🏻新建mod的方法,目前ide,还支持的不是很友好,也不好编程,错误也不好检查。只有去编译目标产物的时候才会发现。 image.png
而脱离目标平台的方法,一些逻辑我是可以提前测试验证的。
注意事项:
java.lang.UnsatisfiedLinkError: dlopen failed: library “librustsdk.so” not found
根据代码是用的什么loadLibrary方法,如果是
是不需要添加lib前缀的,尽管生成的lib文件带有前缀,例如 librust_sdk.so,还有需要留意你在grade里面指定的文件
1 | cargo { |
java.lang.UnsatisfiedLinkError: No implementation found
这个是方法找不到,需要查一下,方法名称和参数是不是对应得上,一个排查方法,就是去看so的导出函数,有没有。
1 | ./ objdump -T librust_sdk.so | grep addNum |
还有一个很容易忽略的点,大坑 apk打包的流程如果是有缓存的话,并不会去检查so是否有更新,写完rust,直接就去编译apk,所以apk里面的so很有可能是旧的,如果是旧的,就需要重新rebuild一次,可以去检查一下。JNI的方法调用,推荐用方法名去做区分,不要用参数重载之类的方法,去做区分,如果你写了一个add函数,发现你多传一个参数,也是可以调的。