Skip to content

Commit 528aa2d

Browse files
authored
[image_picker] Mention launchMode: singleInstance in README (#3759)
Users of the image picker are reporting issues for Android when setting the `launchMode` of the application activity to `singleInstance`. Namely, the image picker will always return `RESULT_CANCELED`. After investigation, it turned out that this problem is inherent by the way Android handles activities with this launch mode: `singleInstance` instructs the framework to open new activities in a new task. As activities cannot communicate between tasks, the image picker activity is unable to relay back the result to the calling activity. This PR updates the README to mention this behavior and provide a workaround. Closes [76856](flutter/flutter#76856).
1 parent 6b7f75b commit 528aa2d

File tree

3 files changed

+85
-44
lines changed

3 files changed

+85
-44
lines changed

packages/image_picker/image_picker/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.8.7+4
2+
3+
* Updates README to mention usage of `launchMode: singleInstance` for Android.
4+
15
## 0.8.7+3
26

37
* Adds handling of unsupported image types to the example.

packages/image_picker/image_picker/README.md

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,54 +12,48 @@ and taking new pictures with the camera.
1212

1313
## Installation
1414

15-
First, add `image_picker` as a [dependency in your pubspec.yaml file](https://flutter.dev/docs/development/platform-integration/platform-channels).
15+
First, add `image_picker` as a
16+
[dependency in your pubspec.yaml file](https://flutter.dev/docs/development/platform-integration/platform-channels).
1617

1718
### iOS
1819

19-
Starting with version **0.8.1** the iOS implementation uses PHPicker to pick (multiple) images on iOS 14 or higher.
20-
As a result of implementing PHPicker it becomes impossible to pick HEIC images on the iOS simulator in iOS 14+. This is a known issue. Please test this on a real device, or test with non-HEIC images until Apple solves this issue. [63426347 - Apple known issue](https://www.google.com/search?q=63426347+apple&sxsrf=ALeKk01YnTMid5S0PYvhL8GbgXJ40ZS[…]t=gws-wiz&ved=0ahUKEwjKh8XH_5HwAhWL_rsIHUmHDN8Q4dUDCA8&uact=5)
21-
22-
Add the following keys to your _Info.plist_ file, located in `<project root>/ios/Runner/Info.plist`:
23-
24-
* `NSPhotoLibraryUsageDescription` - describe why your app needs permission for the photo library. This is called _Privacy - Photo Library Usage Description_ in the visual editor.
25-
* This permission will not be requested if you always pass `false` for `requestFullMetadata`, but App Store policy requires including the plist entry.
26-
* `NSCameraUsageDescription` - describe why your app needs access to the camera. This is called _Privacy - Camera Usage Description_ in the visual editor.
27-
* `NSMicrophoneUsageDescription` - describe why your app needs access to the microphone, if you intend to record videos. This is called _Privacy - Microphone Usage Description_ in the visual editor.
20+
Starting with version **0.8.1** the iOS implementation uses PHPicker to pick
21+
(multiple) images on iOS 14 or higher.
22+
As a result of implementing PHPicker it becomes impossible to pick HEIC images
23+
on the iOS simulator in iOS 14+. This is a known issue. Please test this on a
24+
real device, or test with non-HEIC images until Apple solves this issue.
25+
[63426347 - Apple known issue](https://www.google.com/search?q=63426347+apple&sxsrf=ALeKk01YnTMid5S0PYvhL8GbgXJ40ZS[…]t=gws-wiz&ved=0ahUKEwjKh8XH_5HwAhWL_rsIHUmHDN8Q4dUDCA8&uact=5)
26+
27+
Add the following keys to your _Info.plist_ file, located in
28+
`<project root>/ios/Runner/Info.plist`:
29+
30+
* `NSPhotoLibraryUsageDescription` - describe why your app needs permission for
31+
the photo library. This is called _Privacy - Photo Library Usage Description_ in
32+
the visual editor.
33+
* This permission will not be requested if you always pass `false` for
34+
`requestFullMetadata`, but App Store policy requires including the plist
35+
entry.
36+
* `NSCameraUsageDescription` - describe why your app needs access to the camera.
37+
This is called _Privacy - Camera Usage Description_ in the visual editor.
38+
* `NSMicrophoneUsageDescription` - describe why your app needs access to the
39+
microphone, if you intend to record videos. This is called
40+
_Privacy - Microphone Usage Description_ in the visual editor.
2841

2942
### Android
3043

31-
Starting with version **0.8.1** the Android implementation support to pick (multiple) images on Android 4.3 or higher.
44+
Starting with version **0.8.1** the Android implementation support to pick
45+
(multiple) images on Android 4.3 or higher.
3246

33-
No configuration required - the plugin should work out of the box. It is
34-
however highly recommended to prepare for Android killing the application when
35-
low on memory. How to prepare for this is discussed in the [Handling
36-
MainActivity destruction on Android](#handling-mainactivity-destruction-on-android)
47+
No configuration required - the plugin should work out of the box. It is however
48+
highly recommended to prepare for Android killing the application when low on memory. How to prepare for this is discussed in the
49+
[Handling MainActivity destruction on Android](#handling-mainactivity-destruction-on-android)
3750
section.
3851

39-
It is no longer required to add `android:requestLegacyExternalStorage="true"` as an attribute to the `<application>` tag in AndroidManifest.xml, as `image_picker` has been updated to make use of scoped storage.
40-
41-
**Note:** Images and videos picked using the camera are saved to your application's local cache, and should therefore be expected to only be around temporarily.
42-
If you require your picked image to be stored permanently, it is your responsibility to move it to a more permanent location.
43-
44-
### Example
45-
46-
<?code-excerpt "readme_excerpts.dart (Pick)"?>
47-
``` dart
48-
final ImagePicker picker = ImagePicker();
49-
// Pick an image.
50-
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
51-
// Capture a photo.
52-
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
53-
// Pick a video.
54-
final XFile? galleryVideo =
55-
await picker.pickVideo(source: ImageSource.gallery);
56-
// Capture a video.
57-
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
58-
// Pick multiple images.
59-
final List<XFile> images = await picker.pickMultiImage();
60-
```
52+
It is no longer required to add `android:requestLegacyExternalStorage="true"` as
53+
an attribute to the `<application>` tag in AndroidManifest.xml, as
54+
`image_picker` has been updated to make use of scoped storage.
6155

62-
### Handling MainActivity destruction on Android
56+
#### Handling MainActivity destruction
6357

6458
When under high memory pressure the Android system may kill the MainActivity of
6559
the application using the image_picker. On Android the image_picker makes use
@@ -89,17 +83,59 @@ Future<void> getLostData() async {
8983

9084
This check should always be run at startup in order to detect and handle this
9185
case. Please refer to the
92-
[example app](https://pub.dev/packages/image_picker/example) for a more
93-
complete example of handling this flow.
86+
[example app](https://pub.dev/packages/image_picker/example) for a more complete
87+
example of handling this flow.
88+
89+
#### Permanently storing images and videos
9490

95-
### Android Photo Picker
91+
Images and videos picked using the camera are saved to your application's local
92+
cache, and should therefore be expected to only be around temporarily.
93+
If you require your picked image to be stored permanently, it is your
94+
responsibility to move it to a more permanent location.
9695

97-
This package has optional [Android Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker) functionality.
96+
#### Android Photo Picker
97+
98+
This package has optional
99+
[Android Photo Picker](https://developer.android.com/training/data-storage/shared/photopicker)
100+
functionality.
98101
[Learn how to use it](https://pub.dev/packages/image_picker_android).
99102

103+
#### Using `launchMode: singleInstance`
104+
105+
Launching the image picker from an `Activity` with `launchMode: singleInstance`
106+
will always return `RESULT_CANCELED`.
107+
In this launch mode, new activities are created in a separate [Task][2].
108+
As activities cannot communicate between tasks, the image picker activity cannot
109+
send back its eventual result to the calling activity.
110+
To work around this problem, consider using `launchMode: singleTask` instead.
111+
112+
### Example
113+
114+
<?code-excerpt "readme_excerpts.dart (Pick)"?>
115+
``` dart
116+
final ImagePicker picker = ImagePicker();
117+
// Pick an image.
118+
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
119+
// Capture a photo.
120+
final XFile? photo = await picker.pickImage(source: ImageSource.camera);
121+
// Pick a video.
122+
final XFile? galleryVideo =
123+
await picker.pickVideo(source: ImageSource.gallery);
124+
// Capture a video.
125+
final XFile? cameraVideo = await picker.pickVideo(source: ImageSource.camera);
126+
// Pick multiple images.
127+
final List<XFile> images = await picker.pickMultiImage();
128+
```
129+
100130
## Migrating to 0.8.2+
101131

102-
Starting with version **0.8.2** of the image_picker plugin, new methods have been added for picking files that return `XFile` instances (from the [cross_file](https://pub.dev/packages/cross_file) package) rather than the plugin's own `PickedFile` instances. While the previous methods still exist, it is already recommended to start migrating over to their new equivalents. Eventually, `PickedFile` and the methods that return instances of it will be deprecated and removed.
132+
Starting with version **0.8.2** of the image_picker plugin, new methods have
133+
been added for picking files that return `XFile` instances (from the
134+
[cross_file](https://pub.dev/packages/cross_file) package) rather than the
135+
plugin's own `PickedFile` instances. While the previous methods still exist, it
136+
is already recommended to start migrating over to their new equivalents.
137+
Eventually, `PickedFile` and the methods that return instances of it will be
138+
deprecated and removed.
103139

104140
#### Call the new methods
105141

@@ -111,3 +147,4 @@ Starting with version **0.8.2** of the image_picker plugin, new methods have bee
111147
| `LostData response = await _picker.getLostData()` | `LostDataResponse response = await _picker.retrieveLostData()` |
112148

113149
[1]: https://pub.dev/packages/image_picker_for_web#limitations-on-the-web-platform
150+
[2]: https://developer.android.com/guide/components/activities/tasks-and-back-stack

packages/image_picker/image_picker/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image
33
library, and taking new pictures with the camera.
44
repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker
55
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
6-
version: 0.8.7+3
6+
version: 0.8.7+4
77

88
environment:
99
sdk: ">=2.18.0 <4.0.0"

0 commit comments

Comments
 (0)