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

Flutter安卓端读取外部JSON文件遇存储权限拒绝问题

Android 13+ 加载第三方JSON文件权限问题解决

问题重现

应用在Linux运行正常,但Android端点击按钮加载其他程序导出的JSON文件时,抛出权限错误:

I/flutter (24500): [MethodChannelFilePicker] Platform exception: PlatformException(read_external_storage_denied, User did not allow reading external storage, null, null)
E/flutter (24500): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(read_external_storage_denied, User did not allow reading external storage, null, null)

问题根源

  1. Android 13+权限模型变更:targetSdkVersion≥33时,原READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限已被拆分,通过系统文件选择器(FilePicker依赖组件)访问用户主动选择的文件,无需提前申请存储权限。
  2. 权限申请逻辑错误:Permission.storage.request()在Android 13+实际申请的是媒体文件权限(图片/视频类),与JSON文件需求不匹配,属于冗余操作。
  3. 冗余权限配置:MANAGE_EXTERNAL_STORAGE是特殊全局权限,仅适用于文件管理器类应用,Google Play审核严格,无需添加。

解决方案

1. 清理AndroidManifest.xml权限

删除冗余存储权限,仅保留必要权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

2. 移除无效权限申请逻辑

删除requestPermission()方法及调用,系统文件选择器会在用户选择文件后自动授予临时访问权限,无需提前申请。

3. 优化文件读取代码

避免直接依赖文件路径(Android 13+第三方文件路径可能无法直接访问),优先使用FilePicker提供的字节流读取:

import 'dart:convert';
import 'dart:typed_data';
import 'package:file_picker/file_picker.dart';

Future<void> pickFile(parent) async {
  FilePickerResult? result = await FilePicker.platform.pickFiles(
    type: FileType.custom,
    allowedExtensions: ['json'],
    withData: true, // 直接获取文件字节数据
  );

  if (result != null) {
    try {
      final Uint8List? bytes = result.files.single.bytes;
      if (bytes != null) {
        String fileContent = utf8.decode(bytes);
        Map<String, dynamic> jsonData = jsonDecode(fileContent);
        // 处理解析后的JSON数据
      }
    } catch (e) {
      print('读取或解析JSON错误: $e');
    }
  }
}

兼容旧版本(可选)

若需兼容Android 12及以下版本,可添加版本判断的权限申请:

import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';

Future<void> checkLegacyStoragePermission() async {
  final androidInfo = await DeviceInfoPlugin().androidInfo;
  if (androidInfo.version.sdkInt < 33) {
    final status = await Permission.storage.status;
    if (!status.isGranted) {
      await Permission.storage.request();
    }
  }
}

验证方案

编译运行应用,点击按钮调用文件选择器,选择第三方导出的JSON文件,可正常读取解析,无权限错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:35:28