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

Android 11存储权限如何用Java实现?targetSdk30下intent列表为空如何解决

问题原因

  1. 核心原因是Android 11(API 30)新增的包可见性限制:默认情况下应用无法直接查询设备上其他应用的组件信息,你代码中addIntentsToList方法内部调用的PackageManager.queryIntentActivities()接口在未声明对应查询规则时会返回空列表,直接导致intentList长度为0。
  2. 现有代码中使用Uri.fromFile()传递文件路径的逻辑在Android 7.0及以上版本会触发FileUriExposedException,你当前通过StrictMode临时绕过的方案不合规,Android 11及更高版本运行时也会出现异常。
  3. ACTION_PICK选图逻辑在Android 11分区存储规则下,后续读取图片时会出现权限不足的问题。

解决方案

第一步:添加包可见性声明

在AndroidManifest.xml的<manifest>节点下(和<application>节点平级)添加如下查询规则:

<queries>
    <!-- 声明可查询响应拍照Intent的应用 -->
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
    </intent>
    <!-- 声明可查询响应选图Intent的应用 -->
    <intent>
        <action android:name="android.intent.action.PICK" />
        <data android:mimeType="image/*" />
    </intent>
</queries>

第二步:替换为FileProvider实现文件分享

移除StrictMode的绕过逻辑,改用官方推荐的FileProvider实现跨应用文件传递:

  1. 在res/xml目录下新建file_paths.xml配置文件,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 对应应用私有目录下的Pictures文件夹,可根据自己的临时文件存储路径调整规则 -->
    <external-files-path
        name="temp_images"
        path="Pictures" />
</paths>
  1. 在AndroidManifest.xml的<application>节点内添加FileProvider声明:
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  1. 修改拍照Intent的Uri赋值逻辑:
File tempFile = getTempFile(context);
Uri photoUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    // 7.0及以上用FileProvider生成Uri
    photoUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", tempFile);
} else {
    // 低版本直接用文件Uri
    photoUri = Uri.fromFile(tempFile);
}
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
// 给目标相机应用授予Uri读写权限
takePhotoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

第三步:可选优化(适配分区存储)

如果不需要兼容特别老的系统,建议把选图的ACTION_PICK替换为ACTION_GET_CONTENT,不需要申请存储权限就能直接拿到可访问的图片Uri,适配成本更低:

// 替换原来的pickIntent构造逻辑
Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT);
pickIntent.setType("image/*");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:54:03