diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 17155a7..8664a4b 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + _requestPermission(Permission permission) async { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result == PermissionStatus.granted) { + return true; + } else { + return false; + } + } + } + + void _showPermissionDeniedDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Permission Denied'), + content: const Text( + 'We need permission to access your media to use this feature.'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } + /// The [pickImage] function is used to show the usage of the Image Picker Package. /// The most important part is the [ImagePicker] call. /// You can add a custom [ImagePickerTheme] to the [ImagePicker] if you want to change some of the UI. @@ -113,28 +144,33 @@ class ImagePickerExampleHomePageState /// This function saves the image in a variable and if it's different than the current image it will get displayed in the application. /// When the same image is chosen there will be a snackbar popping up to let you know it's already being displayed. void pickImage() async { - Uint8List? imageInBytes = await showModalBottomSheet( - context: context, - backgroundColor: Colors.white, - builder: (BuildContext context) => ImagePicker( - onError: (error) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(error.message ?? "An error occurred")), - ); - }, - )); - if (imageInBytes != null) { - if (!listEquals(uploadedImage, imageInBytes)) { - setState(() { - uploadedImage = imageInBytes; - }); - } else { - if (!mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(imageAlreadyDisplayedMessage)), - ); + if (await _requestPermission(Permission.storage)) { + Uint8List? imageInBytes = await showModalBottomSheet( + context: context, + backgroundColor: Colors.white, + builder: (BuildContext context) => ImagePicker( + onError: (error) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(error.message ?? "An error occurred")), + ); + }, + )); + if (imageInBytes != null) { + if (!listEquals(uploadedImage, imageInBytes)) { + setState(() { + uploadedImage = imageInBytes; + }); + } else { + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(imageAlreadyDisplayedMessage)), + ); + } } + imageInBytes = null; + } else { + _showPermissionDeniedDialog(); } - imageInBytes = null; } } diff --git a/lib/src/services/permission_service.dart b/lib/src/services/permission_service.dart new file mode 100644 index 0000000..aeccfff --- /dev/null +++ b/lib/src/services/permission_service.dart @@ -0,0 +1,16 @@ +import 'package:permission_handler/permission_handler.dart'; + +class PermissionService { + Future checkAndRequestPermission(Permission permission) async { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result == PermissionStatus.granted) { + return true; + } else { + return false; + } + } + } +} diff --git a/lib/src/ui/image_picker.dart b/lib/src/ui/image_picker.dart index 63a8a9e..a16c7f4 100644 --- a/lib/src/ui/image_picker.dart +++ b/lib/src/ui/image_picker.dart @@ -1,11 +1,8 @@ -// SPDX-FileCopyrightText: 2022 Iconica -// -// SPDX-License-Identifier: BSD-3-Clause - import "package:flutter/material.dart"; import "package:flutter/services.dart"; import "package:flutter_image_picker/flutter_image_picker.dart"; import "package:image_picker/image_picker.dart"; +import 'package:flutter_image_picker/src/services/permission_service.dart'; /// The Image Picker class generates the Image Picker Widget which can be /// displayed in your application. If you call the class you can give it 4 @@ -141,6 +138,14 @@ class ImagePicker extends StatelessWidget { onTap: () async { var navigator = Navigator.of(context); Uint8List? image; + var permissionService = PermissionService(); + bool hasPermission = await permissionService.checkAndRequestPermission( + imageSource == ImageSource.camera ? Permission.camera : Permission.photos, + ); + if (!hasPermission) { + _showPermissionDeniedDialog(context); + return; + } try { image = await (service ?? ImagePickerServiceDefault()) .pickImage(imageSource, config: config); @@ -163,4 +168,25 @@ class ImagePicker extends StatelessWidget { ), ], ); + + void _showPermissionDeniedDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Permission Denied'), + content: const Text( + 'We need permission to access your media to use this feature.'), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 50fb559..119cb83 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: flutter: sdk: flutter image_picker: ^1.1.2 + permission_handler: ^10.0.0 dev_dependencies: flutter_test: