You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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已实现权限申请的桥接逻辑:

  1. 在Cargo.toml中添加依赖:
[dependencies]
android-permissions = "0.4"
  1. 编写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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 10:42:49