-
Notifications
You must be signed in to change notification settings - Fork 29.5k
Closed
flutter/packages
#5009Closed
Copy link
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: crashStack traces logged to the consoleStack traces logged to the consolec: fatal crashCrashes that terminate the processCrashes that terminate the processe: device-specificOnly manifests on certain devicesOnly manifests on certain devicesp: image_pickerThe Image Picker plugin.The Image Picker plugin.packageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team
Description
Issue
Hi, my app is getting crashed while using Image Picker. The app gets crashed when using Pick MultiImage Mode.
Phone Model -> LE2111 (OnePlus 9)
Android Version -> 12
The code being used here is same as the code provided in flutter image picker documentation (example app).
Steps to Reproduce
- Click on multi image picker floating action icon.
- Do not input any maxWidth, maxHeight or quality. Leave all fields blank and click pick.
- Select the photos option from the app drawer of File Manager App.
- Select 3 photos.
- App gets crashed
Expected results: 3 images should have been displayed on screen
Actual results: App is getting crashed
main.dart
import 'package:flutter/material.dart';
import 'package:testingimagepicker/homepage.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
homepage.dart
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:video_player/video_player.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<XFile>? _imageFileList;
void _setImageFileListFromFile(XFile? value) {
_imageFileList = value == null ? null : <XFile>[value];
}
dynamic _pickImageError;
bool isVideo = false;
VideoPlayerController? _controller;
VideoPlayerController? _toBeDisposed;
String? _retrieveDataError;
final ImagePicker _picker = ImagePicker();
final TextEditingController maxWidthController = TextEditingController();
final TextEditingController maxHeightController = TextEditingController();
final TextEditingController qualityController = TextEditingController();
Future<void> _playVideo(XFile? file) async {
if (file != null && mounted) {
await _disposeVideoController();
late VideoPlayerController controller;
if (kIsWeb) {
controller = VideoPlayerController.network(file.path);
} else {
controller = VideoPlayerController.file(File(file.path));
}
_controller = controller;
// In web, most browsers won't honor a programmatic call to .play
// if the video has a sound track (and is not muted).
// Mute the video so it auto-plays in web!
// This is not needed if the call to .play is the result of user
// interaction (clicking on a "play" button, for example).
const double volume = kIsWeb ? 0.0 : 1.0;
await controller.setVolume(volume);
await controller.initialize();
await controller.setLooping(true);
await controller.play();
setState(() {});
}
}
Future<void> _onImageButtonPressed(ImageSource source, {BuildContext? context, bool isMultiImage = false}) async {
if (_controller != null) {
await _controller!.setVolume(0.0);
}
if (isVideo) {
final XFile? file = await _picker.pickVideo(source: source, maxDuration: const Duration(seconds: 10));
await _playVideo(file);
} else if (isMultiImage) {
await _displayPickImageDialog(context!, (double? maxWidth, double? maxHeight, int? quality) async {
try {
final List<XFile>? pickedFileList = await _picker.pickMultiImage(
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_imageFileList = pickedFileList;
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
});
} else {
await _displayPickImageDialog(context!, (double? maxWidth, double? maxHeight, int? quality) async {
try {
final XFile? pickedFile = await _picker.pickImage(
source: source,
maxWidth: maxWidth,
maxHeight: maxHeight,
imageQuality: quality,
);
setState(() {
_setImageFileListFromFile(pickedFile);
});
} catch (e) {
setState(() {
_pickImageError = e;
});
}
});
}
}
@override
void deactivate() {
if (_controller != null) {
_controller!.setVolume(0.0);
_controller!.pause();
}
super.deactivate();
}
@override
void dispose() {
_disposeVideoController();
maxWidthController.dispose();
maxHeightController.dispose();
qualityController.dispose();
super.dispose();
}
Future<void> _disposeVideoController() async {
if (_toBeDisposed != null) {
await _toBeDisposed!.dispose();
}
_toBeDisposed = _controller;
_controller = null;
}
Widget _previewVideo() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_controller == null) {
return const Text(
'You have not yet picked a video',
textAlign: TextAlign.center,
);
}
return Padding(
padding: const EdgeInsets.all(10.0),
child: AspectRatioVideo(_controller),
);
}
Widget _previewImages() {
final Text? retrieveError = _getRetrieveErrorWidget();
if (retrieveError != null) {
return retrieveError;
}
if (_imageFileList != null) {
return Semantics(
label: 'image_picker_example_picked_images',
child: ListView.builder(
key: UniqueKey(),
itemBuilder: (BuildContext context, int index) {
// Why network for web?
// See https://pub.dev/packages/image_picker#getting-ready-for-the-web-platform
return Semantics(
label: 'image_picker_example_picked_image',
child:
kIsWeb ? Image.network(_imageFileList![index].path) : Image.file(File(_imageFileList![index].path)),
);
},
itemCount: _imageFileList!.length,
),
);
} else if (_pickImageError != null) {
return Text(
'Pick image error: $_pickImageError',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
Widget _handlePreview() {
if (isVideo) {
return _previewVideo();
} else {
return _previewImages();
}
}
Future<void> retrieveLostData() async {
final LostDataResponse response = await _picker.retrieveLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
if (response.type == RetrieveType.video) {
isVideo = true;
await _playVideo(response.file);
} else {
isVideo = false;
setState(() {
if (response.files == null) {
_setImageFileListFromFile(response.file);
} else {
_imageFileList = response.files;
}
});
}
} else {
_retrieveDataError = response.exception!.code;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hey'),
),
body: Center(
child: !kIsWeb && defaultTargetPlatform == TargetPlatform.android
? FutureBuilder<void>(
future: retrieveLostData(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
case ConnectionState.done:
return _handlePreview();
default:
if (snapshot.hasError) {
return Text(
'Pick image/video error: ${snapshot.error}}',
textAlign: TextAlign.center,
);
} else {
return const Text(
'You have not yet picked an image.',
textAlign: TextAlign.center,
);
}
}
},
)
: _handlePreview(),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Semantics(
label: 'image_picker_example_from_gallery',
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(ImageSource.gallery, context: context);
},
heroTag: 'image0',
tooltip: 'Pick Image from gallery',
child: const Icon(Icons.photo),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(
ImageSource.gallery,
context: context,
isMultiImage: true,
);
},
heroTag: 'image1',
tooltip: 'Pick Multiple Image from gallery',
child: const Icon(Icons.photo_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
onPressed: () {
isVideo = false;
_onImageButtonPressed(ImageSource.camera, context: context);
},
heroTag: 'image2',
tooltip: 'Take a Photo',
child: const Icon(Icons.camera_alt),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
isVideo = true;
_onImageButtonPressed(ImageSource.gallery);
},
heroTag: 'video0',
tooltip: 'Pick Video from gallery',
child: const Icon(Icons.video_library),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0),
child: FloatingActionButton(
backgroundColor: Colors.red,
onPressed: () {
isVideo = true;
_onImageButtonPressed(ImageSource.camera);
},
heroTag: 'video1',
tooltip: 'Take a Video',
child: const Icon(Icons.videocam),
),
),
],
),
);
}
Text? _getRetrieveErrorWidget() {
if (_retrieveDataError != null) {
final Text result = Text(_retrieveDataError!);
_retrieveDataError = null;
return result;
}
return null;
}
Future<void> _displayPickImageDialog(BuildContext context, OnPickImageCallback onPick) async {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Add optional parameters'),
content: Column(
children: <Widget>[
TextField(
controller: maxWidthController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(hintText: 'Enter maxWidth if desired'),
),
TextField(
controller: maxHeightController,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(hintText: 'Enter maxHeight if desired'),
),
TextField(
controller: qualityController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(hintText: 'Enter quality if desired'),
),
],
),
actions: <Widget>[
TextButton(
child: const Text('CANCEL'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('PICK'),
onPressed: () {
final double? width =
maxWidthController.text.isNotEmpty ? double.parse(maxWidthController.text) : null;
final double? height =
maxHeightController.text.isNotEmpty ? double.parse(maxHeightController.text) : null;
final int? quality = qualityController.text.isNotEmpty ? int.parse(qualityController.text) : null;
onPick(width, height, quality);
Navigator.of(context).pop();
}),
],
);
});
}
}
typedef OnPickImageCallback = void Function(double? maxWidth, double? maxHeight, int? quality);
class AspectRatioVideo extends StatefulWidget {
const AspectRatioVideo(this.controller, {Key? key}) : super(key: key);
final VideoPlayerController? controller;
@override
AspectRatioVideoState createState() => AspectRatioVideoState();
}
class AspectRatioVideoState extends State<AspectRatioVideo> {
VideoPlayerController? get controller => widget.controller;
bool initialized = false;
void _onVideoControllerUpdate() {
if (!mounted) {
return;
}
if (initialized != controller!.value.isInitialized) {
initialized = controller!.value.isInitialized;
setState(() {});
}
}
@override
void initState() {
super.initState();
controller!.addListener(_onVideoControllerUpdate);
}
@override
void dispose() {
controller!.removeListener(_onVideoControllerUpdate);
super.dispose();
}
@override
Widget build(BuildContext context) {
if (initialized) {
return Center(
child: AspectRatio(
aspectRatio: controller!.value.aspectRatio,
child: VideoPlayer(controller!),
),
);
} else {
return Container();
}
}
}
pubspec.yaml
name: testingimagepicker
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.16.2 <3.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
image_picker: ^0.8.5+3
video_player: ^2.4.2
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^1.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
Logs
Showing LE2111 logs:
I/flutter (31129): The Dart VM service is listening on http://127.0.0.1:40411/lKI0jLcJDfg=/
E/AndroidRuntime(31129): FATAL EXCEPTION: main
E/AndroidRuntime(31129): Process: com.example.testingimagepicker, PID: 31129
E/AndroidRuntime(31129): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2346, result=-1, data=Intent { flg=0x1 (has extras) }} to activity {com.example.testingimagepicker/com.example.testingimagepicker.MainActivity}: java.lang.NullPointerException: uri
E/AndroidRuntime(31129): at android.app.ActivityThread.deliverResults(ActivityThread.java:5510)
E/AndroidRuntime(31129): at android.app.ActivityThread.handleSendResult(ActivityThread.java:5549)
E/AndroidRuntime(31129): at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:54)
E/AndroidRuntime(31129): at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
E/AndroidRuntime(31129): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
E/AndroidRuntime(31129): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
E/AndroidRuntime(31129): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2341)
E/AndroidRuntime(31129): at android.os.Handler.dispatchMessage(Handler.java:106)
E/AndroidRuntime(31129): at android.os.Looper.loopOnce(Looper.java:233)
E/AndroidRuntime(31129): at android.os.Looper.loop(Looper.java:344)
E/AndroidRuntime(31129): at android.app.ActivityThread.main(ActivityThread.java:8184)
E/AndroidRuntime(31129): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(31129): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
E/AndroidRuntime(31129): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
E/AndroidRuntime(31129): Caused by: java.lang.NullPointerException: uri
E/AndroidRuntime(31129): at java.util.Objects.requireNonNull(Objects.java:245)
E/AndroidRuntime(31129): at android.content.ContentResolver.openInputStream(ContentResolver.java:1519)
E/AndroidRuntime(31129): at io.flutter.plugins.imagepicker.FileUtils.getPathFromUri(FileUtils.java:45)
E/AndroidRuntime(31129): at io.flutter.plugins.imagepicker.ImagePickerDelegate.handleChooseMultiImageResult(ImagePickerDelegate.java:504)
E/AndroidRuntime(31129): at io.flutter.plugins.imagepicker.ImagePickerDelegate.onActivityResult(ImagePickerDelegate.java:467)
E/AndroidRuntime(31129): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry$FlutterEngineActivityPluginBinding.onActivityResult(FlutterEngineConnectionRegistry.java:805)
E/AndroidRuntime(31129): at io.flutter.embedding.engine.FlutterEngineConnectionRegistry.onActivityResult(FlutterEngineConnectionRegistry.java:428)
E/AndroidRuntime(31129): at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onActivityResult(FlutterActivityAndFragmentDelegate.java:802)
E/AndroidRuntime(31129): at io.flutter.embedding.android.FlutterActivity.onActivityResult(FlutterActivity.java:724)
E/AndroidRuntime(31129): at android.app.Activity.dispatchActivityResult(Activity.java:8471)
E/AndroidRuntime(31129): at android.app.ActivityThread.deliverResults(ActivityThread.java:5503)
E/AndroidRuntime(31129): ... 13 more
[✓] Flutter (Channel stable, 3.0.0, on Microsoft Windows [Version 10.0.19044.1706], locale en-IN)
• Flutter version 3.0.0 at C:\Users\aniru\Documents\flutter_windows_2.5.3-stable\flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision ee4e09cce0 (9 days ago), 2022-05-09 16:45:18 -0700
• Engine revision d1b9a6938a
• Dart version 2.17.0
• DevTools version 2.12.2
Checking Android licenses is taking an unexpectedly long time...[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at C:\Users\aniru\AppData\Local\Android\sdk
• Platform android-31, build-tools 31.0.0
• Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 11.0.11+9-b60-7590822)
• All Android licenses accepted.
[✓] Chrome - develop for the web
• Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe
[!] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.3)
• Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
• Visual Studio Community 2022 version 17.1.32328.378
✗ The current Visual Studio installation is incomplete. Please reinstall Visual Studio.
[✓] Android Studio (version 2021.1)
• Android Studio at C:\Program Files\Android\Android Studio
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.11+9-b60-7590822)
[✓] VS Code (version 1.67.1)
• VS Code at C:\Users\aniru\AppData\Local\Programs\Microsoft VS Code
• Flutter extension version 3.40.0
[✓] Connected device (4 available)
• LE2111 (mobile) • c04dff6d • android-arm64 • Android 12 (API 31)
• Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19044.1706]
• Chrome (web) • chrome • web-javascript • Google Chrome 101.0.4951.67
• Edge (web) • edge • web-javascript • Microsoft Edge 101.0.1210.47
[✓] HTTP Host Availability
• All required HTTP hosts are available
! Doctor found issues in 1 category.
Record_2022-05-19-15-38-08.mp4
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listc: crashStack traces logged to the consoleStack traces logged to the consolec: fatal crashCrashes that terminate the processCrashes that terminate the processe: device-specificOnly manifests on certain devicesOnly manifests on certain devicesp: image_pickerThe Image Picker plugin.The Image Picker plugin.packageflutter/packages repository. See also p: labels.flutter/packages repository. See also p: labels.platform-androidAndroid applications specificallyAndroid applications specificallyr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team