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

升级至Android API 33后存储权限问题求助

Android 13(SDK33)下Ionic+Capacitor应用图片存储失败的解决方案

问题背景

基于Ionic、Angular和Capacitor开发的应用,使用cordova-diagnostic-plugin实现图片下载功能,将目标Android SDK版本升级至33后,存储功能出现异常。

当前表现

  • 点击下载图片时,弹出存储权限请求对话框,提示允许应用访问设备文件
  • 按文档重新请求权限时,权限对话框不再弹出,日志输出如下:

Requesting permission for android.permission.READ_EXTERNAL_STORAGE

Requesting permissions

Notifying listeners for event pause

No listeners found for event pause

App paused

Unable to find a Capacitor plugin to handle permission requestCode, trying Cordova plugins 0

预期表现

点击下载按钮后,图片能正常下载并存储到设备中。

环境信息

  • Ionic CLI: 7.1.1
  • Ionic Framework: @ionic/angular 7.2.0
  • @angular/cli: 16.1.0
  • @ionic/angular-toolkit: 9.0.0
  • Capacitor相关:
    • Capacitor CLI: 5.2.2
    • @capacitor/android: 5.2.2
    • @capacitor/core: 5.2.2
    • @capacitor/ios: 5.2.2
  • 系统环境:
    • NodeJS: v18.10.0
    • npm: 8.19.2
  • 目标Android SDK版本:33
  • 插件版本:cordova.plugins.diagnostic: ^7.1.2

相关代码片段

const destinationUri = this.platform.is("android")
    ? "file:///storage/emulated/0/"
    : this.ionicFile.dataDirectory;

const blob: Blob = res.data;

if (this.platform.is("android")) {
    try {
        await this.ionicFile.checkDir(destinationUri, "dcim/WXS ONE");
    } catch {
        await this.ionicFile.createDir(destinationUri, "dcim/WXS ONE", false);
    }
}

解决方案

1. 适配Android 13的存储权限逻辑

Android 13(SDK33)废弃了READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,针对图片文件需使用READ_MEDIA_IMAGES权限(写入无需单独申请,只要是文件创建者或拥有读取权限即可):

  • 首先升级cordova-diagnostic-plugin到支持Android 13的版本(至少v7.1.3,建议最新版):
npm install cordova.plugins.diagnostic@latest
  • 修改权限请求代码,区分Android版本:
import { Diagnostic } from '@ionic-native/diagnostic/ngx';

async requestStoragePermissions() {
    if (this.platform.is('android')) {
        const androidVersion = parseInt(this.platform.version().split('.')[0], 10);
        const permissions = androidVersion >= 13 
            ? [Diagnostic.permission.READ_MEDIA_IMAGES]
            : [Diagnostic.permission.READ_EXTERNAL_STORAGE, Diagnostic.permission.WRITE_EXTERNAL_STORAGE];
        
        const status = await this.diagnostic.requestPermissions(permissions);
        const hasPermission = androidVersion >=13 
            ? status[Diagnostic.permission.READ_MEDIA_IMAGES] === Diagnostic.permissionStatus.GRANTED
            : status[Diagnostic.permission.READ_EXTERNAL_STORAGE] === Diagnostic.permissionStatus.GRANTED;
        
        if (hasPermission) {
            this.downloadImage();
        } else {
            console.log('存储权限被拒绝,无法下载图片');
        }
    }
}

2. 替换文件存储方式(推荐)

使用Capacitor官方的@capacitor/filesystem插件替代Cordova文件插件,该插件原生适配Android 13存储机制:

  • 安装插件并同步项目:
npm install @capacitor/filesystem
npx cap sync
  • 修改存储逻辑,将图片保存到系统公共图片目录:
import { Filesystem, Directory } from '@capacitor/filesystem';

async saveImageToDevice(blob: Blob) {
    if (this.platform.is('android')) {
        // 将Blob转换为base64格式
        const base64 = await new Promise<string>((resolve) => {
            const reader = new FileReader();
            reader.onloadend = () => resolve(reader.result as string);
            reader.readAsDataURL(blob);
        });
        // 保存到公共图片目录的自定义子文件夹
        await Filesystem.writeFile({
            path: 'WXS ONE/downloaded-image.jpg',
            data: base64.split(',')[1], // 移除base64前缀
            directory: Directory.Pictures,
            recursive: true
        });
    } else {
        // iOS端存储逻辑
        await Filesystem.writeFile({
            path: 'WXS ONE/downloaded-image.jpg',
            data: (await this.blobToBase64(blob)).split(',')[1],
            directory: Directory.Data,
            recursive: true
        });
    }
}

3. 配置AndroidManifest.xml权限

在android/app/src/main/AndroidManifest.xml中添加版本区分的权限声明:

<!-- Android 13及以上权限 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- 低版本兼容权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />

4. 修复Capacitor与Cordova插件兼容问题

日志中Unable to find a Capacitor plugin to handle permission requestCode是因为Capacitor 5对Cordova插件权限处理有变更,升级插件后重新同步Android项目:

npx cap sync android

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:07:10