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

Android 10无法访问应用外部文件的技术求助

解决Android 10下无法访问公共下载目录的问题

你遇到的问题核心是Android 10(API 29)引入的分区存储(Scoped Storage)机制——即便你配置了READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限,默认情况下也无法直接通过Environment.getExternalStoragePublicDirectory()访问公共目录的文件。下面分两种方案帮你解决:

一、临时过渡方案(快速解决)

如果想继续沿用旧的文件访问逻辑,可以在AndroidManifest.xmlapplication标签中添加android:requestLegacyExternalStorage="true",强制禁用分区存储:

<application 
    android:allowBackup="true" 
    android:largeHeap="true" 
    android:fullBackupContent="@xml/backup_descriptor" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:roundIcon="@mipmap/ic_launcher_round" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"
    android:requestLegacyExternalStorage="true"> <!-- 添加这一行 -->
    <!-- 其他组件配置 -->
</application>

这个配置会让应用在Android 10上使用传统存储模式,你之前的Environment.getExternalStoragePublicDirectory(DIRECTORY_DOWNLOADS)就能正常获取文件列表了。注意这是过渡方案,在Android 11及以上版本需要额外适配。

二、长期适配方案(符合新存储规范)

如果要适配Android 10+的分区存储,推荐使用以下两种方式:

1. 使用MediaStore查询公共目录文件

对于下载目录的文件,可以通过MediaStore.Downloads来查询,示例代码:

ContentResolver resolver = context.getContentResolver();
Uri uri = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Downloads._ID, MediaStore.Downloads.DISPLAY_NAME};

Cursor cursor = resolver.query(uri, projection, null, null, null);
if (cursor != null) {
    while (cursor.moveToNext()) {
        String fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Downloads.DISPLAY_NAME));
        // 处理文件名或获取文件路径
    }
    cursor.close();
}

2. 使用存储访问框架(SAF)让用户选择文件/目录

如果需要让用户手动选择下载目录的文件,可以启动系统文件选择器:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); // 允许选择所有类型文件
((Activity) context).startActivityForResult(intent, REQUEST_CODE_PICK_FILE);

然后在onActivityResult(或AndroidX的registerForActivityResult)中获取选中文件的Uri,进行后续操作。

额外优化:权限申请代码调整

你的权限申请逻辑里包含了FOREGROUND_SERVICE权限,这个权限在API 29中属于正常权限,不需要动态申请,所以可以简化判断逻辑:

if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
        || ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions((Activity) context,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_CODE_FOLDER_CONF);
}

最后补充:你能正常访问应用内的getExternalFilesDir()目录,是因为这个目录属于应用专属存储区域,分区存储机制不会限制应用对自身专属目录的访问权限。

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

火山引擎 最新活动