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

Flutter Android端image_picker调用pickImage报MissingPluginException

问题场景
  • 基于Flutter框架开发仅适配Android端的应用,使用image_picker: ^0.8.5+3插件实现相机拍摄、相册选取图片功能,业务逻辑采用GetX框架编写
  • 适配目标为Android 29+版本,已在AndroidManifest.xml中添加android:requestLegacyExternalStorage="true"配置,未做iOS端适配
  • 调用选图方法时持续抛出异常,已尝试公开社区同类问题的常规解决方案,均未生效

抛出的异常信息如下:

Unhandled Exception: MissingPluginException(No implementation found for method pickImage on channel plugins.flutter.io/image_picker_android)

关联代码与报错日志

1. GetX图片选取业务逻辑代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';

class ImageController extends GetxController {
var selectedImagePath = ''.obs;
var selectedImageSize = ''.obs;

void getImage(ImageSource imageSource) async {
final pickedFile = await ImagePicker().pickImage(source: imageSource);
if (pickedFile != null) {
  selectedImagePath.value = pickedFile.path;
  selectedImageSize.value =
      ((File(selectedImagePath.value).lengthSync() / 1024 / 1024)
              .toStringAsFixed(2) +
          "Mb");
} else {
  selectedImagePath.value = '';
  selectedImageSize.value = '';

  Get.snackbar(
    "Please Select Image",
    "No Image Selected",
    snackPosition: SnackPosition.BOTTOM,
    backgroundColor: Colors.red,
    colorText: Colors.white,
    borderRadius: 10,
    margin: EdgeInsets.all(10),
    borderColor: Colors.red,
    borderWidth: 2,
    duration: Duration(seconds: 2),
    icon: Icon(
      Icons.error,
      color: Colors.white,
    ),
  );
}
}
}

2. UI层选图功能调用代码

GestureDetector(
onTap: () {
  Get.bottomSheet(
    Container(
      height: currentOrientation == Orientation.portrait
          ? screenHeight * 0.10
          : screenHeight * 0.22,
      width: double.infinity,
      decoration: BoxDecoration(
        color: ProjectColors.kPrimaryColor,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(
            currentOrientation == Orientation.portrait
                ? screenHeight * 0.02
                : screenHeight * 0.05,
          ),
          topRight: Radius.circular(
            currentOrientation == Orientation.portrait
                ? screenHeight * 0.02
                : screenHeight * 0.05,
          ),
        ),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          GestureDetector(
            onTap: () {
              imageController
                  .getImage(ImageSource.camera);
            },
            child: Icon(
              Icons.camera_alt_outlined,
              color: ProjectColors.kWhiteColor,
              size: currentOrientation ==
                      Orientation.portrait
                  ? screenHeight * 0.06
                  : screenHeight * 0.15,
            ),
          ),
          SizedBox(
            width:
                currentOrientation == Orientation.portrait
                    ? screenWidth * 0.20
                    : screenWidth * 0.15,
          ),
          GestureDetector(
            onTap: () {
              imageController
                  .getImage(ImageSource.gallery);
            },
            child: Icon(
              Icons.image_outlined,
              color: ProjectColors.kWhiteColor,
              size: currentOrientation ==
                      Orientation.portrait
                  ? screenHeight * 0.06
                  : screenHeight * 0.15,
            ),
          ),
        ],
      ),
    ),
  );
},
child: Obx(
  () => imageController.selectedImagePath.value == ''
      ? Container(
          height:
              currentOrientation == Orientation.portrait
                  ? screenHeight * 0.20
                  : screenHeight * 0.50,
          width:
              currentOrientation == Orientation.portrait
                  ? screenWidth * 0.85
                  : double.infinity,
          color: Colors.white,
          child: Icon(
            Icons.add_box_sharp,
            color: ProjectColors.kPrimaryColor,
            size:
                currentOrientation == Orientation.portrait
                    ? screenHeight * 0.06
                    : screenHeight * 0.10,
          ),
        )
      : Image.file(
          File(imageController.selectedImagePath.value),
          fit: BoxFit.cover,
        ),
),
),

3. 完整运行报错日志

E/flutter ( 5139): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: 
MissingPluginException(No implementation found for method pickImage on channel 
plugins.flutter.io/image_picker_android)
E/flutter ( 5139): #0      MethodChannel._invokeMethod 
(package:flutter/src/services/platform_channel.dart:165:7)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): #1      ImagePickerAndroid.getImage 
(package:image_picker_android/image_picker_android.dart:161:26)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): #2      ImageController.getImage 
(package:cede_mobile/controller/select_image.dart:11:24)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): 
E/flutter ( 5139): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: 
MissingPluginException(No implementation found for method pickImage on channel 
plugins.flutter.io/image_picker_android)
E/flutter ( 5139): #0      MethodChannel._invokeMethod 
(package:flutter/src/services/platform_channel.dart:165:7)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): #1      ImagePickerAndroid.getImage 
(package:image_picker_android/image_picker_android.dart:161:26)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): #2      ImageController.getImage 
(package:cede_mobile/controller/select_image.dart:11:24)
E/flutter ( 5139): <asynchronous suspension>
E/flutter ( 5139): 
排查与解决步骤

按顺序执行以下操作,绝大多数同类问题可在前三步解决:

  • 全量清理重建项目:热重载、热重启不会注册新增原生插件的通道,必须执行完整清理流程
    flutter clean
    flutter pub get
    
    执行完成后,完全卸载设备/模拟器上已安装的旧版本应用,重新执行flutter run全量编译安装,不要使用热重载启动应用。
  • 检查Android端基础配置:
    • 打开android/app/build.gradle文件,确认minSdkVersion配置不低于20,这是image_picker 0.8.5+3要求的最低Android版本
    • 执行flutter build apk --debug查看构建日志,确认是否存在Manifest合并冲突,比如引入android:requestLegacyExternalStorage属性时未声明xmlns:tools命名空间,或其他依赖覆盖了插件的清单配置
    • 如果项目中自定义了FlutterEngine、继承了FlutterActivity做二次开发,需要手动在引擎注册逻辑中添加ImagePickerAndroid插件的注册,不要完全依赖自动生成的插件注册逻辑
  • 修复pub缓存损坏问题:0.8.5版本的image_picker首次拆分Android端为独立的image_picker_android原生包,本地pub缓存损坏时会导致原生代码未被正确引入,直接删除本地pub缓存目录(Windows路径为C:\Users\用户名\AppData\Local\Pub\Cache,Mac路径为~/.pub-cache),重新执行flutter pub get拉取依赖
  • 版本降级验证:如果以上操作都无效,将pubspec.yaml中image_picker版本调整为^0.8.4+4,该版本未拆分Android端独立实现包,不存在通道注册失败的兼容问题,重新编译验证功能是否正常,排除0.8.5+3版本本身的兼容bug
  • 权限逻辑修正:Android 11及以上版本会自动忽略android:requestLegacyExternalStorage="true"配置,且image_picker调用系统选图器不需要申请全量存储权限,不要在选图前额外申请存储权限,避免权限逻辑冲突导致插件调用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:57:15