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

Android 14中如何获取外部存储Documents文件夹的读写权限?

Android 14 下访问Documents文件夹备份文件的实现方案

核心思路

Android 14 中,若无法申请MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,应使用**存储访问框架(SAF,Storage Access Framework)**访问Documents文件夹。这是官方推荐的共享存储访问方式,无需特殊权限,通过用户手动选择文件夹/文件获取访问权限,完全符合系统权限规范。

具体实现步骤

1. 启动SAF选择Documents文件夹

调用系统文件选择器,引导用户选择Documents文件夹,获取文件夹的Uri权限:

// 定义请求码,用于回调识别
private static final int REQUEST_CODE_PICK_DOCUMENTS = 1001;

// 启动文件夹选择流程
private void launchDocumentsPicker() {
    Intent pickerIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    // 可选:默认定位到Documents文件夹(Android 11+支持)
    Uri initialDir = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    pickerIntent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialDir);
    startActivityForResult(pickerIntent, REQUEST_CODE_PICK_DOCUMENTS);
}

2. 处理选择结果并持久化权限

在onActivityResult(或AndroidX的registerForActivityResult)中获取选中文件夹的Uri,申请持久化权限确保后续无需重复选择:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_PICK_DOCUMENTS && resultCode == RESULT_OK) {
        if (data != null) {
            Uri folderUri = data.getData();
            // 持久化读写权限,直到用户手动撤销
            getContentResolver().takePersistableUriPermission(
                folderUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
            );
            // 将Uri保存到SharedPreferences,方便后续直接使用
            saveFolderUri(folderUri.toString());
            // 此时已具备Documents文件夹的读写权限
        }
    }
}

// 辅助方法:保存Uri到本地存储
private void saveFolderUri(String uriStr) {
    SharedPreferences prefs = getSharedPreferences("AppStoragePrefs", MODE_PRIVATE);
    prefs.edit().putString("selected_documents_uri", uriStr).apply();
}

3. 读写Documents文件夹内的备份文件

通过已保存的Uri,使用ContentResolver完成文件读写操作:

// 从SharedPreferences获取已保存的文件夹Uri
private Uri getSavedFolderUri() {
    SharedPreferences prefs = getSharedPreferences("AppStoragePrefs", MODE_PRIVATE);
    String uriStr = prefs.getString("selected_documents_uri", null);
    return uriStr != null ? Uri.parse(uriStr) : null;
}

// 创建备份文件到Documents文件夹
private void createBackup(String backupFileName) {
    Uri folderUri = getSavedFolderUri();
    if (folderUri == null) {
        // 未选择文件夹,重新启动选择流程
        launchDocumentsPicker();
        return;
    }

    // 构建备份文件的Uri
    Uri backupFileUri = DocumentsContract.buildDocumentUriUsingTree(
        folderUri,
        DocumentsContract.getTreeDocumentId(folderUri) + "/" + backupFileName
    );

    try (OutputStream outputStream = getContentResolver().openOutputStream(backupFileUri)) {
        // 写入备份内容(示例为字符串,实际可替换为文件流)
        String backupContent = "备份数据内容";
        outputStream.write(backupContent.getBytes());
        Toast.makeText(this, "备份完成", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "备份失败", Toast.LENGTH_SHORT).show();
    }
}

// 读取Documents文件夹内的备份文件
private String readBackup(String backupFileName) {
    Uri folderUri = getSavedFolderUri();
    if (folderUri == null) {
        launchDocumentsPicker();
        return null;
    }

    Uri backupFileUri = DocumentsContract.buildDocumentUriUsingTree(
        folderUri,
        DocumentsContract.getTreeDocumentId(folderUri) + "/" + backupFileName
    );

    try (InputStream inputStream = getContentResolver().openInputStream(backupFileUri)) {
        byte[] buffer = new byte[inputStream.available()];
        inputStream.read(buffer);
        return new String(buffer);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

4. Android 14 适配注意事项

  • Android 14 无需申请READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限,SAF操作完全基于用户授予的Uri权限。
  • 若仅需访问单个备份文件,可使用Intent.ACTION_OPEN_DOCUMENT替代文件夹选择,流程逻辑一致。
  • 持久化的Uri权限会一直保留,直到用户在系统设置中主动撤销应用的存储访问权限。

内容的提问来源于stack exchange,提问作者Daniel Román

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 16:01:31