Android平台Rust应用如何申请READ_EXTERNAL_STORAGE权限?
Android平台Rust应用申请外部存储读取权限的实现方案
在Android平台上,Rust作为Native层代码无法直接调用系统权限申请API,必须依托Android的Java/Kotlin层权限机制来实现,以下是两种可行方案:
方案一:手动实现JNI桥接(适配已有Java权限逻辑)
1. 声明权限
首先在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ 若读取媒体文件,需替换为对应细分权限,例如: --> <!-- <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> -->
2. Java层封装权限操作
复用你现有Java版本的权限逻辑,封装成可被Rust调用的静态方法,并维护当前Activity引用:
import android.app.Activity; import android.content.pm.PackageManager; import androidx.core.content.ContextCompat; import androidx.core.app.ActivityCompat; public class PermissionHelper { private static Activity sCurrentActivity; public static void setCurrentActivity(Activity activity) { sCurrentActivity = activity; } // 检查读取存储权限是否已授权 public static boolean hasReadStoragePermission() { if (sCurrentActivity == null) return false; return ContextCompat.checkSelfPermission(sCurrentActivity, android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; } // 申请读取存储权限 public static void requestReadStoragePermission(int requestCode) { if (sCurrentActivity == null) return; ActivityCompat.requestPermissions(sCurrentActivity, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, requestCode); } }
同时在Activity中处理权限申请回调:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限授权成功,可通知Rust继续执行文件读取逻辑 } else { // 权限被拒绝,处理对应逻辑 } } }
3. Rust层通过JNI调用Java方法
使用jni crate实现JNI交互,在Rust中调用Java层的权限检查和申请方法:
首先在Cargo.toml中添加依赖:
[dependencies] jni = { version = "0.21", default-features = false, features = ["invocation"] }
然后编写Rust代码:
use jni::{JNIEnv, objects::JClass, sys::jint}; // 检查读取存储权限 #[no_mangle] pub extern "system" fn Java_com_example_yourapp_PermissionHelper_hasReadStoragePermission( env: JNIEnv, _class: JClass ) -> bool { let helper_class = env.find_class("com/example/yourapp/PermissionHelper").unwrap(); env.call_static_method( helper_class, "hasReadStoragePermission", "()Z", &[] ).unwrap().z().unwrap() } // 请求读取存储权限 #[no_mangle] pub extern "system" fn Java_com_example_yourapp_PermissionHelper_requestReadStoragePermission( env: JNIEnv, _class: JClass, request_code: jint ) { let helper_class = env.find_class("com/example/yourapp/PermissionHelper").unwrap(); env.call_static_method( helper_class, "requestReadStoragePermission", "(I)V", &[request_code.into()] ).unwrap(); } // 业务逻辑中使用 fn try_read_file() { // 先检查权限 let has_permission = unsafe { // 需根据实际JNI环境调用对应方法,此处为简化示例 Java_com_example_yourapp_PermissionHelper_hasReadStoragePermission(...) }; if has_permission { match std::fs::File::open("/sdcard/tmp/demo.ts") { Ok(f) => println!("文件打开成功"), Err(e) => eprintln!("文件打开失败: {:?}", e), } } else { // 申请权限 unsafe { Java_com_example_yourapp_PermissionHelper_requestReadStoragePermission(..., 1); } // 等待用户授权后再尝试读取 } }
方案二:使用封装好的Rust Crate
借助android-permissions crate简化JNI层的封装操作,该crate已实现权限申请的桥接逻辑:
- 在
Cargo.toml中添加依赖:
[dependencies] android-permissions = "0.4"
- 编写Rust代码:
use android_permissions::{request_permissions, Permission}; use std::fs::File; fn main() { // 定义需要申请的权限 let permissions = vec![Permission::ReadExternalStorage]; // 申请权限 match request_permissions(&permissions) { Ok(granted) => { if granted.contains(&Permission::ReadExternalStorage) { // 权限已授权,读取文件 match File::open("/sdcard/tmp/demo.ts") { Ok(_) => eprintln!("文件读取成功"), Err(e) => eprintln!("文件读取失败: {:?}", e), } } else { eprintln!("读取存储权限被拒绝"); } } Err(e) => eprintln!("权限申请出错: {:?}", e), } }
注意:使用该crate仍需在AndroidManifest.xml中声明对应权限,且需确保应用运行在Android 6.0及以上版本。
版本兼容性说明
- Android 6.0(API 23)及以上:必须动态申请危险权限,仅在Manifest声明无效。
- Android 13(API 33)及以上:
READ_EXTERNAL_STORAGE权限被废弃,需根据文件类型使用READ_MEDIA_IMAGES、READ_MEDIA_VIDEO或READ_MEDIA_AUDIO等细分权限。
内容的提问来源于stack exchange,提问作者Mutant Bob
相关产品推荐
相关产品推荐

