安卓studio 安装SDK 和 NDK
所有操作是mac m1 上操作的
NDK 可以在 Android studio 设置里面,搜索sdk ,然后看下SDK 位置例如我下面的位置:
/Users/admin/Library/Android/sdk/ndk
Android NDK(Native Development Kit)生成一个独立的工具链
# 其中/Users/admin/go/ndk/arm64 这个地址是生成各种平台目录
# aarch64-linux-android
python3 /Users/admin/Library/Android/sdk/ndk/27.0.12077973/build/tools/make_standalone_toolchain.py --api 27 --arch arm64 --install-dir /Users/admin/go/ndk/arm64
# armv7-linux-androideabi
python3 /Users/admin/Library/Android/sdk/ndk/27.0.12077973/build/tools/make_standalone_toolchain.py --api 27 --arch arm --install-dir /Users/admin/go/ndk/arm
# x86_64-linux-android
python3 /Users/admin/Library/Android/sdk/ndk/27.0.12077973/build/tools/make_standalone_toolchain.py --api 27 --arch x86_64 --install-dir /Users/admin/go/ndk/x86_64
编辑 ~/.cargo/config 文件添加
# 这个是我api 27版本的,30版本好像ar要改
[target.aarch64-linux-android]
ar = "/Users/admin/go/ndk/arm64/bin/llvm-ar"
linker = "/Users/admin/go/ndk/arm64/bin/aarch64-linux-android-clang"
[target.armv7-linux-androideabi]
ar = "/Users/admin/go/ndk/arm/bin/llvm-ar"
linker = "/Users/admin/go/ndk/arm/bin/arm-linux-androideabi-clang"
[target.x86_64-linux-android]
ar = "/Users/admin/go/ndk/x86_64/bin/llvm-ar"
linker = "/Users/admin/go/ndk/x86_64/bin/x86_64-linux-android-clang"
30 版本ar路径变了
[target.aarch64-linux-android]
ar = "/Users/你的用户名/NDK/arm64/bin/aarch64-linux-android-ar"
linker = "/Users/你的用户名/NDK/arm64/bin/aarch64-linux-android-clang"
[target.armv7-linux-androideabi]
ar = "/Users/你的用户名/NDK/arm/bin/arm-linux-androideabi-ar"
linker = "/Users/你的用户名/NDK/arm/bin/arm-linux-androideabi-clang"
[target.i686-linux-android]
ar = "/Users/你的用户名/NDK/x86/bin/i686-linux-android-ar"
linker = "/Users/你的用户名/NDK/x86/bin/i686-linux-android-clang"
rust 程序流程
创建项目
cargo new --lib my_crypto_lib
修改 Cargo.toml
# 下面几个值是优化包的体积 打出来so很小
[profile.release]
lto = true
opt-level = "z"
panic = "abort"
codegen-units = 1
[dependencies]
jni = "0.21.1"
[lib]
name = "my_crypto_lib"
crate-type = ["cdylib"]
rust程序
use jni::objects::{JClass, JString};
use jni::JNIEnv;
use jni::sys::{jint,jstring};
// 注意如果包名带下划线需要写成 _1
#[no_mangle]
pub extern "C" fn Java_com_example_rust_1app_RustClass_add(_env: JNIEnv, _class: JClass, a: jint, b: jint) -> jint {
a + b
}
#[no_mangle]
pub extern "C" fn Java_com_example_rust_1app_RustClass_processStringo<'local>(mut env: JNIEnv<'local>, _class: JClass<'local>, input: JString<'local>) -> jstring {
// First, we have to get the string out of Java. Check out the `strings`
// module for more info on how this works.
let input: String =
env.get_string(&input).expect("Couldn't get java string!").into();
// Then we have to create a new Java string to return. Again, more info
// in the `strings` module.
let output = env.new_string(format!("Hello, {}!", input))
.expect("Couldn't create java string!");
// Finally, extract the raw pointer to return.
output.into_raw()
}
确认rust 跨平台是否安装
rustup show
安装多个安卓架构平台
# arm64
rustup target install aarch64-linux-android
# arm32
rustup target install armv7-linux-androideabi
# amd64
rustup target install x86_64-linux-android
# amd32
rustup target install i686-linux-android
rustup show
验证编译rust so 动态库
cargo build --target aarch64-linux-android --release
cargo build --target armv7-linux-androideabi --release
cargo build --target x86_64-linux-android --release
cargo build --target i686-linux-android --release
更小的生成方式
cargo install cargo-ndk
确认
cargo intall --list
多个平台打包,这个方式比上面cargo build 要小很多具体原因不知道是什么,ndk这个库估计做了优化
# 会生成到项目目录 jniLibs 下,
cargo ndk -t armeabi-v7a -t arm64-v8a -t x86 -t x86_64 -o ./jniLibs build --release
生成如下:
再jniLibs目录查看下大小
find . -type f -exec du -h {} +
打包出来很小
xz:jniLibs (master*) $ find . -type f -exec du -h {} +
8.0K ./.DS_Store
80K ./armeabi-v7a/libmy_crypto_lib.so
264K ./arm64-v8a/libmy_crypto_lib.so
128K ./x86_64/libmy_crypto_lib.so
然后吧 jniLibs 复制到java项目
如图:
build.gradle 修改下引入
android {
......
sourceSets {
main {
jniLibs.srcDirs = ['jniLibs']
}
androidTest {
jniLibs.srcDirs = ['jniLibs']
}
}
....
}
如图
安卓java程序
package com.example.rust_app;
public class RustClass {
static {
System.loadLibrary("my_crypto_lib");
}
public native int add(int a, int b);
public native String processStringo(String a);
public void addTest() {
int result = add(99, 5);
System.out.println("Result: " + result);
String resultStr = processStringo(",world");
System.out.println("string:" + resultStr);
}
}
测试效果
借鉴了文章: https://blog.csdn.net/ysy950803/article/details/122882360
rust jni 文档地址: https://docs.rs/jni/latest/jni/