Flutter中如何在Android 13设备的Download文件夹保存文件?
解决Android 13下Flutter保存文件到Download文件夹的权限问题
Android 13(API 33)对存储权限体系做了重大调整:原WRITE_EXTERNAL_STORAGE/READ_EXTERNAL_STORAGE权限被废弃,针对公共Download目录的文件操作逻辑也发生了变化,这是导致你原有代码失效的核心原因。以下是具体解决方案:
核心逻辑调整
1. 权限请求区分Android版本
根据系统版本选择对应的权限检查逻辑,避免在Android 13上请求已失效的Permission.storage:
import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; Future<int> _getAndroidSdkVersion() async { final androidInfo = await DeviceInfoPlugin().androidInfo; return androidInfo.version.sdkInt; } Future<void> checkAndRequestStoragePermission() async { final sdkVersion = await _getAndroidSdkVersion(); if (sdkVersion >= 33) { // Android 13+:若需直接用File API操作Download目录,需申请MANAGE_EXTERNAL_STORAGE final manageStatus = await Permission.manageExternalStorage.status; if (manageStatus.isDenied) { final result = await Permission.manageExternalStorage.request(); if (result.isDenied) await openAppSettings(); } else if (manageStatus.isPermanentlyDenied) { await openAppSettings(); } else { // 执行文件操作 } } else { // Android 13以下:沿用原有存储权限逻辑 final storageStatus = await Permission.storage.status; if (storageStatus.isDenied) { final result = await Permission.storage.request(); if (result.isDenied) await openAppSettings(); } else if (storageStatus.isPermanentlyDenied) { await openAppSettings(); } else { // 执行文件操作 } } }
2. 推荐:使用MediaStore保存文件(无需特殊权限)
Android 13允许应用直接向公共Download目录写入文件,无需申请存储权限,推荐通过MediaStore实现(避免依赖特殊权限):
Flutter端代码
import 'dart:typed_data'; import 'package:flutter/services.dart'; Future<bool> saveToDownloads(Uint8List fileBytes, String fileName) async { const channel = MethodChannel('your_app/file_save'); try { await channel.invokeMethod('saveFileToDownloads', { 'bytes': fileBytes, 'fileName': fileName, 'mimeType': 'application/octet-stream', // 根据文件类型修改,如text/plain、image/png }); return true; } on PlatformException catch (e) { print('保存失败:${e.message}'); return false; } }
Android原生端代码(MainActivity.kt)
import android.content.ContentValues import android.net.Uri import android.os.Build import android.provider.MediaStore import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "your_app/file_save" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "saveFileToDownloads") { val bytes = call.argument<ByteArray>("bytes") val fileName = call.argument<String>("fileName") val mimeType = call.argument<String>("mimeType") if (bytes != null && fileName != null && mimeType != null) { val success = saveFileToDownloads(bytes, fileName, mimeType) result.success(success) } else { result.error("INVALID_ARGS", "参数缺失", null) } } else { result.notImplemented() } } } private fun saveFileToDownloads(bytes: ByteArray, fileName: String, mimeType: String): Boolean { val contentValues = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, fileName) put(MediaStore.Downloads.MIME_TYPE, mimeType) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { put(MediaStore.Downloads.IS_PENDING, 1) } } contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)?.let { uri -> contentResolver.openOutputStream(uri)?.use { it.write(bytes) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { contentValues.clear() contentValues.put(MediaStore.Downloads.IS_PENDING, 0) contentResolver.update(uri, contentValues, null, null) } return true } return false } }
权限声明配置
在AndroidManifest.xml中添加对应权限:
<!-- Android 13以下的存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 13+的特殊存储权限(仅当使用File API时需要) --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
注意事项
MANAGE_EXTERNAL_STORAGE是特殊权限,Google Play对其审核严格,仅文件管理器、备份工具等核心场景允许使用,优先用MediaStore方案。- 确保
permission_handler和device_info_plus依赖为最新版本,适配Android 13权限体系。
内容的提问来源于stack exchange,提问作者Manish Tiwari
相关产品推荐
相关产品推荐

