flutter - 无法在 Flutter Web 上使用图像选择器选择图像(MissingPluginException)

标签 flutter dart file-permissions flutter-web

下面我分享了我的 flutter 代码,它只需选择一个图像并在获得所需权限后将其显示在屏幕上。然而,该代码在 Android 上运行良好,但在我尝试在网络上上传图像时出现 MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods) 异常。

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Project2',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  File _file = File("zz");

  uploadImage() async {
    final ImagePicker _picker = ImagePicker();
    final XFile? image;

    var permissionStatus = requestPermissions();
    if (await permissionStatus.isGranted) {
      image = await _picker.pickImage(source: ImageSource.gallery);
      var selected = File(image!.path);

      setState(() {
        _file = selected;
      });
    } else {
      showToast("Permission not granted");
    }
  }

  Future<PermissionStatus> requestPermissions() async {
    await Permission.photos.request();
    return Permission.photos.status;
  }

  void showToast(String message) {
    Fluttertoast.showToast(
      msg: message,
      toastLength: Toast.LENGTH_SHORT,
      gravity: ToastGravity.BOTTOM,
      timeInSecForIosWeb: 1,
      backgroundColor: Colors.red,
      textColor: Colors.white,
      fontSize: 16.0,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Upload Image"),
      ),
      body: Column(
        children: [
          (_file.path != "zz")
              ? Image.file(_file)
              : Image.asset("assets/img/images.jpeg"),
          SizedBox(
            height: 20,
            width: double.infinity,
          ),
          ElevatedButton(
            onPressed: () => uploadImage(),
            child: Text("Upload"),
          )
        ],
      ),
    );
  }
}

以下是按下上传按钮时生成的堆栈跟踪:

Error: MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)
    at Object.throw_ [as throw] (http://localhost:64931/dart_sdk.js:5041:11)
    at MethodChannel._invokeMethod (http://localhost:64931/packages/flutter/src/services/system_channels.dart.lib.js:943:21)
    at _invokeMethod.next (<anonymous>)
    at http://localhost:64931/dart_sdk.js:37403:33
    at _RootZone.runUnary (http://localhost:64931/dart_sdk.js:37274:59)
    at _FutureListener.thenAwait.handleValue (http://localhost:64931/dart_sdk.js:32530:29)
    at handleValueCallback (http://localhost:64931/dart_sdk.js:33057:49)
    at Function._propagateToListeners (http://localhost:64931/dart_sdk.js:33095:17)
    at _Future.new.[_completeWithValue] (http://localhost:64931/dart_sdk.js:32943:23)
    at async._AsyncCallbackEntry.new.callback (http://localhost:64931/dart_sdk.js:32964:35)
    at Object._microtaskLoop (http://localhost:64931/dart_sdk.js:37526:13)
    at _startMicrotaskLoop (http://localhost:64931/dart_sdk.js:37532:13)
    at http://localhost:64931/dart_sdk.js:33303:9

pubspec.yaml 文件:

environment:
  sdk: ">=2.12.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  image_picker: ^0.8.3+3
  permission_handler: ^8.1.4+2
  fluttertoast: ^8.0.8

  cupertino_icons: ^1.0.2

dev_dependencies:
  flutter_test:
    sdk: flutter


flutter:
  uses-material-design: true

  assets:
    - assets/img/images.jpeg

PS:flutter cleanflutter run 不适用于 Web 版本。

最佳答案

问题出在 Web 中的权限处理程序包。 Permissions Handler package 仅针对 Android 和 IOS 构建,在 Web 平台上上传图像不需要权限,因此在 Web 上使用它会出现 MissingPluginException

通过为 Web 和移动平台添加条件语句和单独实现解决了该问题。

检查平台是否为web,首先需要添加:

import 'package:flutter/foundation.dart' show kIsWeb;

uploadImage() 方法更改为:

  uploadImage() async {
    var permissionStatus = requestPermissions();

    // MOBILE
    if (!kIsWeb && await permissionStatus.isGranted) {
      final ImagePicker _picker = ImagePicker();
      XFile? image = await _picker.pickImage(source: ImageSource.gallery);

      if (image != null) {
        var selected = File(image.path);

        setState(() {
          _file = selected;
        });
      } else {
        showToast("No file selected");
      }
    }
    // WEB
    else if (kIsWeb) {
      final ImagePicker _picker = ImagePicker();
      XFile? image = await _picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        var f = await image.readAsBytes();
        setState(() {
          _file = File("a");
          webImage = f;
        });
      } else {
        showToast("No file selected");
      }
    } else {
      showToast("Permission not granted");
    }
  }

最后在 build() 方法中为 Web 和 Android Image 添加单独的实现:

  File _file = File("zz");
  Uint8List webImage = Uint8List(10);
@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Upload Image"),
      ),
      body: Column(
        children: [
          (_file.path == "zz")
              ? Image.asset("assets/img/images.jpeg")
              : (kIsWeb)
                  ? Image.memory(webImage)
                  : Image.file(_file),
          SizedBox(
            height: 20,
            width: double.infinity,
          ),
          ElevatedButton(
            onPressed: () => uploadImage(),
            child: Text("Upload"),
          )
        ],
      ),
    );
  }

关于flutter - 无法在 Flutter Web 上使用图像选择器选择图像(MissingPluginException),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68982252/

相关文章:

ios - flutter : Unable to redirect to specific screen on Notification click when app is in background but not terminated in iOS

http - 为什么 dio 发布空表单数据?

flutter - 如何在后台运行蓝牙和位置代码?

flutter auto_route |如何使用 BlocProvider 包装路由?

ftp - lftp:如何递归设置权限;首先按目录而不是按文件

flutter - 使用 'GeoLocator' 包时无法获取纬度和经度

flutter - Dart:使用 map 过滤列表

通过 map 函数将 Dart 映射到另一个 map

linux - 为什么 Apache + PHP 需要执行权限才能写入文件?

emacs - 在 Emacs 中使用 su/sudo 打开文件