You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 11中如何访问/storage/emulated/0/Android/data/com.abc.appName目录?

在Android 11中访问Android/data目录的正确姿势

嘿,这个问题我太熟悉了!Android 11开始推行的**Scoped Storage(分区存储)**就是导致你代码返回null的核心原因——它把每个应用的Android/data/[包名]目录彻底隔离了,默认情况下你根本没法直接遍历整个Android/data目录,更别说访问其他应用的子目录了。下面分情况给你讲解决办法:

一、访问自己应用的Android/data目录(最推荐)

如果你的目标是访问自己应用/storage/emulated/0/Android/data/com.abc.appName,完全不需要绕弯路,直接用系统提供的API就能拿到,还不需要额外权限:

// 获取自己应用的Android/data/com.abc.appName/files目录
File ownDataFilesDir = getExternalFilesDir(null);
// 要是想拿到上级的com.abc.appName目录,调用getParent()就行
File ownRootDataDir = ownDataFilesDir.getParentFile();

// 现在就可以正常遍历这个目录下的文件了
File[] files = ownRootDataDir.listFiles();
if (files != null) {
    for (File file : files) {
        // 处理你的文件逻辑
    }
}

这个方法完全符合Android 11的存储规范,不会有任何权限问题。

二、访问其他应用的Android/data目录(受限)

如果是要访问其他应用Android/data子目录,Android 11不允许直接通过文件路径访问,只能通过**SAF(存储访问框架)**让用户手动选择目标目录,代码示例如下:

1. 启动SAF选择目录

private static final int REQUEST_CODE_PICK_DIR = 1001;

// 触发目录选择
private void pickOtherAppDataDir() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, REQUEST_CODE_PICK_DIR);
}

2. 处理用户选择的结果

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_PICK_DIR && resultCode == RESULT_OK) {
        // 获取用户选择的目录Uri
        Uri treeUri = data.getData();
        // 申请持久访问权限,避免重启后失效
        getContentResolver().takePersistableUriPermission(treeUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        
        // 用DocumentFile来操作目录下的内容
        DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
        if (pickedDir != null && pickedDir.isDirectory()) {
            for (DocumentFile file : pickedDir.listFiles()) {
                // 处理每个文件/子目录
            }
        }
    }
}

注意:这种方式必须由用户手动选择目录,你的应用不能静默访问——这是Android 11强制的安全限制,没有任何绕过的办法。

三、关于MANAGE_EXTERNAL_STORAGE权限(不推荐)

你可能听说过MANAGE_EXTERNAL_STORAGE权限,它可以让应用访问所有外部存储,但Google对这个权限的审核极其严格,只有文件管理器、备份工具这类必须全局访问存储的应用才能通过审核。如果你的应用不符合这个场景,别浪费时间:

1. 清单文件声明权限

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
                android:minSdkVersion="30" />

2. 引导用户开启权限

if (!Environment.isExternalStorageManager()) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
    startActivity(intent);
}

再次强调:除非你的应用是专门的文件管理类工具,否则Google Play会拒绝你的上架申请,而且这种方式也破坏了分区存储的安全设计,尽量别用。


内容的提问来源于stack exchange,提问作者enthusiastdev

火山引擎 最新活动