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

Flutter 1.22.0适配Android13相册权限失败,无需升级的解决办法?

Android 13下Flutter 1.22.0图片选择权限问题

我的应用图片选择功能在Android 13版本前运行正常,但在Android 13上无法获取相册访问权限。项目基于Flutter 1.22.0(搭配Dart 2.10,非空安全版本),已在AndroidManifest中添加以下权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>

使用image_picker包调用图片选择方法时,抛出如下错误:

PlatformException(photo_access_denied, The user did not allow photo access., null, null)

问题根源是旧版本库未适配Android 13,由于升级Flutter版本耗时较长,想寻求无需升级即可解决的方案。


解决方案

1. 手动用旧版权限请求库适配逻辑

旧版image_picker未适配Android 13的READ_MEDIA_IMAGES权限请求,可搭配支持非空安全的旧版permission_handler(如permission_handler: ^5.1.0+2)手动处理权限:

  • 在pubspec.yaml添加依赖:
    dependencies:
      permission_handler: ^5.1.0+2
    
  • 在调用image_picker前先请求权限:
    import 'package:permission_handler/permission_handler.dart';
    import 'package:image_picker/image_picker.dart';
    import 'package:flutter/foundation.dart';
    
    Future<void> pickImage() async {
      PermissionStatus status;
      // 区分Android版本处理权限请求
      if (defaultTargetPlatform == TargetPlatform.android) {
        // 需引入device_info_plus旧版本(如^2.1.0)获取Android版本
        final androidInfo = await DeviceInfoPlugin().androidInfo;
        if (androidInfo.version.sdkInt >= 33) {
          status = await Permission.photos.request();
        } else {
          status = await Permission.storage.request();
        }
      } else {
        status = await Permission.photos.request();
      }
    
      if (status.isGranted) {
        final XFile? image = await ImagePicker().pickImage(source: ImageSource.gallery);
        // 处理选中的图片
      } else {
        // 处理权限拒绝的逻辑
      }
    }
    

2. 自定义原生图片选择逻辑(绕开旧库限制)

通过Flutter MethodChannel对接Android原生代码,使用Android 13推荐的ActivityResultContracts.PickVisualMedia实现图片选择,该方式无需手动申请权限(系统自动处理授权流程):

  • Flutter端:注册MethodChannel并调用原生方法

    import 'package:flutter/services.dart';
    
    static const platform = MethodChannel('com.yourapp/image_picker');
    
    Future<void> pickImageFromNative() async {
      try {
        final String? imagePath = await platform.invokeMethod('pickImage');
        if (imagePath != null) {
          // 处理图片路径
        }
      } on PlatformException catch (e) {
        print("图片选择失败: ${e.message}");
      }
    }
    
  • Android原生端:在MainActivity中实现逻辑

    class MainActivity : FlutterActivity() {
        private val CHANNEL = "com.yourapp/image_picker"
        private val pickVisualMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
            val path = uri?.let { getRealPathFromURI(it) }
            methodChannel.invokeMethod("imageSelected", path)
        }
    
        private lateinit var methodChannel: MethodChannel
    
        override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
            super.configureFlutterEngine(flutterEngine)
            methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
            methodChannel.setMethodCallHandler { call, result ->
                when (call.method) {
                    "pickImage" -> {
                        pickVisualMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
                        result.success(null)
                    }
                    else -> result.notImplemented()
                }
            }
        }
    
        // 将Uri转换为真实文件路径的辅助方法
        private fun getRealPathFromURI(contentUri: Uri): String? {
            val projection = arrayOf(MediaStore.Images.Media.DATA)
            val cursor = contentResolver.query(contentUri, projection, null, null, null) ?: return null
            val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            cursor.moveToFirst()
            val path = cursor.getString(columnIndex)
            cursor.close()
            return path
        }
    }
    

3. 升级Android编译版本配合权限配置

将Android项目的compileSdkVersion升级到33(Flutter 1.22.0支持该版本),确保AndroidManifest中已添加READ_MEDIA_IMAGES权限,再结合手动权限请求逻辑,可让旧版image_picker在Android 13上正常工作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:30:37