基于android-activity的Rust安卓应用如何访问ActivityCompat类?
问题:无法在Rust原生安卓应用中找到ActivityCompat类
我有一个基于android-activity的Rust原生安卓应用,想要调用ActivityCompat.requestPermission(),但调用jni_env.find_class("androidx/core/app/ActivityCompat")时出现异常,而jni_env.find_class("java/lang/String")能正常返回结果。我猜测ActivityCompat类所在的jar包未被包含在android-activity包装器中。
代码文件
Cargo.toml
[package] name = "check2" version = "0.1.0" edition = "2021" [dependencies] android-activity = { version = "*", features = ["native-activity"] } android_logger = "*" jni="0.19.0" ndk-context="*" log="*" [lib] crate-type = ["lib", "cdylib"] [package.metadata.android] apk_label = "demonstration of missing java class" target_sdk_version = 29 min_sdk_version = 29 #runtime_libs = "libs" [[package.metadata.android.application.activity.intent_filter]] actions = ["android.intent.action.MAIN"] categories = [ "android.intent.category.LAUNCHER", ]
lib.rs
use android_activity::AndroidApp; use jni::errors::Error; use jni::JavaVM; use log::debug; use std::ffi::c_void; pub fn adapt_android_env() -> Result<(JavaVM, *mut c_void), Error> { let ctx = ndk_context::android_context(); let vm = unsafe { jni::JavaVM::from_raw(ctx.vm().cast()) }?; let activity = ctx.context(); Ok((vm, activity)) } #[no_mangle] fn android_main(_android_app: AndroidApp) { android_logger::init_once( android_logger::Config::default().with_max_level(log::LevelFilter::Trace), ); debug!("application starting"); let (jvm, _activity) = adapt_android_env().unwrap(); let jni_env = jvm.attach_current_thread().unwrap(); // { let x = jni_env.find_class("java/lang/String"); debug!("java class string is {:?}", x); } { let x = jni_env.find_class("androidx/core/app/ActivityCompat"); debug!("java class ActivityCompat is {:?}", x); } debug!("exception state is {:?}", jni_env.exception_check()); debug!("exception clear is {:?}", jni_env.exception_clear()); debug!("application ending"); }
解决方法
1. 添加AndroidX Core依赖
android-activity默认仅依赖系统原生Activity相关库,AndroidX Core属于额外依赖,需要在Cargo.toml的安卓元数据中配置引入:
[package.metadata.android] apk_label = "demonstration of missing java class" target_sdk_version = 29 min_sdk_version = 29 # 添加AndroidX Core依赖 android_gradle_plugins = [ "androidx.core:core:1.12.0" ]
该配置会让构建工具自动引入AndroidX Core库,确保ActivityCompat类可被加载。
2. 通过Activity的ClassLoader加载类
直接调用find_class可能因类加载器范围问题失败,可借助已有的Activity实例获取其类加载器来加载目标类:
修改lib.rs中的代码:
use android_activity::AndroidApp; use jni::errors::Error; use jni::{JavaVM, objects::JObject}; use log::debug; pub fn adapt_android_env() -> Result<(JavaVM, JObject), Error> { let ctx = ndk_context::android_context(); let vm = unsafe { JavaVM::from_raw(ctx.vm().cast()) }?; // 将原始指针转为JObject let activity = unsafe { JObject::from_raw(ctx.context().cast()) }; Ok((vm, activity)) } #[no_mangle] fn android_main(_android_app: AndroidApp) { android_logger::init_once( android_logger::Config::default().with_max_level(log::LevelFilter::Trace), ); debug!("application starting"); let (jvm, activity) = adapt_android_env().unwrap(); let jni_env = jvm.attach_current_thread().unwrap(); // 获取Activity的ClassLoader let class_loader = jni_env.call_method( activity, "getClassLoader", "()Ljava/lang/ClassLoader;", &[] )?.l()?; // 使用ClassLoader加载ActivityCompat { let x = jni_env.find_class_with_loader("androidx/core/app/ActivityCompat", class_loader); debug!("java class ActivityCompat is {:?}", x); } { let x = jni_env.find_class("java/lang/String"); debug!("java class string is {:?}", x); } debug!("exception state is {:?}", jni_env.exception_check()); debug!("exception clear is {:?}", jni_env.exception_clear()); debug!("application ending"); }
Activity的类加载器包含了AndroidX依赖的加载路径,以此加载类成功率更高。
3. 更新构建工具
确保cargo-apk为最新版本,旧版本对AndroidX依赖支持可能不完善:
cargo install cargo-apk --force
内容的提问来源于stack exchange,提问作者Mutant Bob
相关产品推荐
相关产品推荐

