1. 下载和配置 NDK
首先,从 Android NDK 下载页面 下载并安装最新版本的 Android NDK。
在安装完成后,确保能够找到 NDK 的安装路径并配置工具链。您将使用这个工具链来交叉编译 Rust 代码为 Android 的本地库。
2. 创建 Rust 库项目
使用以下命令在命令行中创建一个新的 Rust 库项目:
cargo new android_test_lib --lib
此命令会生成一个新的 Rust 项目目录 android_test_lib
,并包含一个简单的库文件结构。
3. 配置 Cargo.toml
编辑项目中的 Cargo.toml
文件,指定该库的构建类型,并添加依赖项:
[package]
name = "android_lib_test"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
jni = "0.21.1"
解释:
[lib]
中的crate-type = ["cdylib"]
指定 Rust 将构建一个 C 兼容的动态库,以便 Android 使用。jni = "0.21.1"
是用于与 Java 进行交互的 JNI 库,允许我们在 Rust 中调用 JNI 方法。
4. 配置 .cargo/config.toml
在项目根目录下创建 .cargo
文件夹,并在其中添加 config.toml
文件,配置 Android 的交叉编译工具链:
mkdir .cargo
touch .cargo/config.toml
目录结构
编辑 config.toml
文件,指定交叉编译时使用的工具链路径:
[target.aarch64-linux-android]
linker = "D:/android-ndk-r27c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd"
# 注意文件路径
解释:
- 这里的
linker
配置项指定了 Android NDK 中clang
编译器的位置,您需要根据自己的实际路径进行修改。
5. 添加目标平台支持
在命令行中运行以下命令,确保您的 Rust 环境支持目标架构:
rustup target list
如果 aarch64-linux-android
目标没有显示为已安装,使用以下命令安装:
rustup target add aarch64-linux-android
6. 编写 Rust 代码
编辑 src/lib.rs
文件,编写您的 Rust 代码并实现 JNI 接口:
use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jstring;
#[no_mangle]
pub extern "system" fn Java_com_suxii_myapplicationrust_Hello_say(
mut env: JNIEnv,
class: JClass,
input: JString,
) -> jstring {
let world: String = env.get_string(&input).expect("invalid pattern string").into();
let output = env.new_string(format!("Hello, {}! this is rust", world)).expect("Couldn't create java string!");
output.into_raw()
}
解释:
#[no_mangle]
:防止 Rust 编译器对函数名进行修改,以保证 JNI 函数名称与 Java 端的声明一致。extern "system" fn Java_com_suxii_myapplicationrust_Hello_say
:JNI 函数,名称必须符合Java_包名_类名_方法名
的格式。env.get_string(&input).expect("invalid pattern string").into();
:将 Java 字符串转换为 Rust 字符串。env.new_string(format!("Hello, {}! this is rust", world))
:创建一个新的 Java 字符串并返回给 Java。
7. 编译 Rust 库
使用以下命令为 Android 构建 release 版本的动态库:
cargo build --target aarch64-linux-android --release
编译完成后,生成的 libandroid_lib_test.so
文件位于 target/aarch64-linux-android/release/
目录下。
8. 配置 Android 项目
打开 Android 项目的 app/build.gradle
文件,在 android
块下添加对本地库的支持:
android {
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
packagingOptions {
jniLibs {
useLegacyPackaging = true
}
}
splits {
abi {
enable true
reset()
include 'arm64-v8a'
universalApk true
}
}
}
解释:
jniLibs.srcDirs = ['src/main/jniLibs']
:指定 Android 项目中用于存放本地库.so
文件的目录。useLegacyPackaging = true
:使用传统的 JNI 库打包方式。splits.abi { enable true; include 'arm64-v8a'; }
:为arm64-v8a
架构构建 APK。
接下来,在 src/main/
目录下创建 jniLibs/arm64-v8a/
目录,并将生成的 libandroid_lib_test.so
文件放入其中。
目录结构为:
9. 创建 Java 接口
在 Android 项目中创建一个新的 Hello
类来调用 Rust 编写的本地方法:
public class Hello {
static {
System.loadLibrary("android_lib_test");
}
public native String say(String str);
}
解释:
System.loadLibrary("android_lib_test");
:加载 Rust 编写的本地库。public native String say(String str);
:声明本地方法say
,该方法接收一个字符串参数并返回一个字符串。
10. 调用 Rust 函数
在 Java 中,创建 Hello
类的实例并调用 say
方法:
Hello hello = new Hello();
String message = hello.say("World");
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
解释:
Hello hello = new Hello();
:创建Hello
类的实例。String message = hello.say("World");
:调用本地方法say
,并传入字符串"World"
,获取返回的字符串。Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
:将返回的消息显示在 Android 的Toast
中。
评论 (0)