Below I'm sharing my flutter code that simply selects an Image and displays it on screen after taking the required permissions. The code, however, runs fine on Android but gives a MissingPluginException(No implementation found for method requestPermissions on channel flutter.baseflow.com/permissions/methods)
exception when I try to upload image on web.
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"),
)
],
),
);
}
}
Following is the generated stacktrace on pressing upload button:
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
file:
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 clean
and flutter run
isn't working for Web version.
The problem is with the permissions handler package in Web. Permissions Handler package is built only for Android and IOS, and no permission is required to upload image on Web Platform, so using it on Web gives MissingPluginException
.
The problem was resolved by adding conditional statements and separate implementations for Web And Mobile Platforms.
To check if the platform is web, you first need to add:
import 'package:flutter/foundation.dart' show kIsWeb;
Change the uploadImage()
method as:
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");
}
}
And then finally add seperate implementations for Web and Android Image in build()
method:
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"),
)
],
),
);
}