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

Android SDK34中requestPermissions不弹权限弹窗,SDK29正常

问题分析与解决方案

核心原因

Android 14(API 34)对存储权限做了进一步限制:READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE已被系统废弃,当应用targetSdkVersion≥33时,请求这两个权限会被系统直接拒绝,不会弹出授权弹窗。而Android 10(API 29)虽然引入了分区存储,但仍兼容旧权限逻辑,所以你的新版本在API 29设备上能正常工作。

另外从API 30开始,保存图片到公共图库等场景已经不需要WRITE_EXTERNAL_STORAGE权限,使用MediaStore API即可完成操作。

解决方案

1. 适配权限声明(AndroidManifest.xml)

根据不同API等级声明对应权限,避免无效权限请求:

<!-- API 32及以下设备需要的旧存储权限 -->
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

<!-- API 33及以上设备需要的媒体读取权限(仅针对图片场景) -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

2. 动态请求权限逻辑适配

根据设备API版本,动态选择要请求的权限:

private void requestStoragePermissions() {
    List<String> permissions = new ArrayList<>();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        // Android 13+,请求图片读取权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)
                != PackageManager.PERMISSION_GRANTED) {
            permissions.add(Manifest.permission.READ_MEDIA_IMAGES);
        }
    } else {
        // Android 12及以下,请求旧存储权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
        }
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
    }

    if (!permissions.isEmpty()) {
        requestPermissions(permissions.toArray(new String[0]), READ_STORAGE_RESPONSE);
    } else {
        // 权限已就绪,执行图片编辑保存逻辑
        handleImageOperations();
    }
}

3. 替换图片保存逻辑(无需WRITE权限)

使用MediaStore API保存图片到公共图库,无需申请WRITE_EXTERNAL_STORAGE:

private Uri saveEditedImage(Bitmap editedBitmap) {
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, "edit_img_" + System.currentTimeMillis() + ".png");
    contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
    // 指定保存到图库的子目录,方便用户查找
    contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/YourAppFolder");

    Uri imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
    if (imageUri == null) return null;

    try (OutputStream outputStream = getContentResolver().openOutputStream(imageUri)) {
        editedBitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
        return imageUri;
    } catch (IOException e) {
        e.printStackTrace();
        // 保存失败,删除空文件
        getContentResolver().delete(imageUri, null, null);
        return null;
    }
}

额外说明

  • 如果你的应用仅需保存自己生成的图片,无需读取用户其他图库内容,那么API 33+甚至不需要申请READ_MEDIA_IMAGES权限。
  • 若需读取用户图库中的图片用于编辑,才需要在API 33+请求READ_MEDIA_IMAGES。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:05:31