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

Android 11 无法读取指定应用Android/data目录文件的解决方案求助

Android 11+ 访问其他应用Android/data目录失效解决方案

问题原因

Android 11(API 30)开始系统强制启用*分区存储(Scoped Storage)*机制,第三方应用默认被禁止直接访问其他应用的Android/data/、Android/obb/私有目录,因此你原来的直接拼接路径读取文件的逻辑会失效。

可行解决方案

场景1:目标文件所属的应用也是你开发的

这种优先用官方推荐的跨应用共享方案,无需申请特殊权限,兼容性最好:

  • 方案1:通过ContentProvider共享文件
    在提供录音文件的应用中注册ContentProvider,暴露对应Recordings目录下的文件资源,你的访问方应用通过ContentResolver即可查询、读取对应的文件,是跨应用共享数据的标准实现。
  • 方案2:同签名应用配置sharedUserId
    如果两个应用使用同一套签名打包,可以在两个应用的AndroidManifest.xml的<manifest>标签中配置相同的android:sharedUserId值,配置后两个应用会运行在同一个沙箱环境,可以直接互相访问私有目录。注意:如果应用已经上线,修改sharedUserId会导致老用户无法覆盖安装,需谨慎使用。

场景2:目标文件所属的应用不是你开发的,无法修改对方代码

方案A:申请全量存储管理权限(MANAGE_EXTERNAL_STORAGE)

该权限属于特殊权限,授权后可以访问外部存储的所有目录,包括其他应用的私有目录。

  1. 首先在AndroidManifest.xml中声明权限:
<!-- 兼容低版本存储权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 11及以上需要的全量存储权限 -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  1. 运行时引导用户授权:
// 权限申请请求码
private static final int REQUEST_MANAGE_STORAGE = 1001;
private static final int REQUEST_READ_STORAGE = 1002;

private void checkPermissionAndLoadFiles() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        if (Environment.isExternalStorageManager()) {
            // 已获得权限,直接读取文件
            loadRecordingFiles();
        } else {
            // 跳转到系统设置页引导用户授权
            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            intent.setData(Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, REQUEST_MANAGE_STORAGE);
        }
    } else {
        // 低版本申请普通存储权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            loadRecordingFiles();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_READ_STORAGE);
        }
    }
}

// 你原有逻辑封装成该方法即可
private void loadRecordingFiles() {
    String path = Environment.getExternalStorageDirectory().toString() + "/Android/data/.../files/Recordings";
    File directory = new File(path);
    File[] files = directory.listFiles();
    if (directory.canRead() && files != null) {
        showRecFiles(files);
    } else {
        Toast.makeText(this, "Empty!!!", Toast.LENGTH_SHORT).show();
    }
}

// 权限申请回调处理
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_MANAGE_STORAGE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        if (Environment.isExternalStorageManager()) {
            loadRecordingFiles();
        } else {
            Toast.makeText(this, "未获得存储权限,无法读取文件", Toast.LENGTH_SHORT).show();
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_READ_STORAGE) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            loadRecordingFiles();
        } else {
            Toast.makeText(this, "未获得存储权限,无法读取文件", Toast.LENGTH_SHORT).show();
        }
    }
}

注意:如果你的应用需要上架谷歌Play商店,该权限仅允许文件管理器、备份、杀毒等必须访问全量存储的应用申请,不符合使用场景的应用会被拒审或下架。

方案B:使用存储访问框架(SAF)引导用户主动授权目录

无需申请特殊权限,也符合谷歌应用商店规则,通过系统的文件选择器引导用户手动选中目标Recordings目录,授权后即可读写该目录下的所有内容,缺点是需要用户手动操作选择目录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:36:04