Skip to content

Commit 9ef18bc

Browse files
authored
[image_picker]Android update cache (flutter#4124)
1 parent 6056abe commit 9ef18bc

File tree

8 files changed

+100
-26
lines changed

8 files changed

+100
-26
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.4
2+
3+
* Update `ImagePickerCache` to cache multiple files.
4+
15
## 0.8.3+3
26

37
* Fix pickImage not returning a value on iOS when dismissing PHPicker sheet by swiping.

packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerCache.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@
1010
import androidx.annotation.Nullable;
1111
import androidx.annotation.VisibleForTesting;
1212
import io.flutter.plugin.common.MethodCall;
13+
import java.util.ArrayList;
1314
import java.util.HashMap;
15+
import java.util.HashSet;
1416
import java.util.Map;
17+
import java.util.Set;
1518

1619
class ImagePickerCache {
1720

1821
static final String MAP_KEY_PATH = "path";
22+
static final String MAP_KEY_PATH_LIST = "pathList";
1923
static final String MAP_KEY_MAX_WIDTH = "maxWidth";
2024
static final String MAP_KEY_MAX_HEIGHT = "maxHeight";
2125
static final String MAP_KEY_IMAGE_QUALITY = "imageQuality";
@@ -50,7 +54,8 @@ class ImagePickerCache {
5054
}
5155

5256
void saveTypeWithMethodCallName(String methodCallName) {
53-
if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE)) {
57+
if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_IMAGE)
58+
| methodCallName.equals(ImagePickerPlugin.METHOD_CALL_MULTI_IMAGE)) {
5459
setType("image");
5560
} else if (methodCallName.equals(ImagePickerPlugin.METHOD_CALL_VIDEO)) {
5661
setType("video");
@@ -99,11 +104,13 @@ String retrievePendingCameraMediaUriPath() {
99104
}
100105

101106
void saveResult(
102-
@Nullable String path, @Nullable String errorCode, @Nullable String errorMessage) {
107+
@Nullable ArrayList<String> path, @Nullable String errorCode, @Nullable String errorMessage) {
103108

109+
Set<String> imageSet = new HashSet<>();
110+
imageSet.addAll(path);
104111
SharedPreferences.Editor editor = prefs.edit();
105112
if (path != null) {
106-
editor.putString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, path);
113+
editor.putStringSet(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, imageSet);
107114
}
108115
if (errorCode != null) {
109116
editor.putString(SHARED_PREFERENCE_ERROR_CODE_KEY, errorCode);
@@ -121,12 +128,17 @@ void clear() {
121128
Map<String, Object> getCacheMap() {
122129

123130
Map<String, Object> resultMap = new HashMap<>();
131+
ArrayList<String> pathList = new ArrayList<>();
124132
boolean hasData = false;
125133

126134
if (prefs.contains(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY)) {
127-
final String imagePathValue = prefs.getString(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, "");
128-
resultMap.put(MAP_KEY_PATH, imagePathValue);
129-
hasData = true;
135+
final Set<String> imagePathList =
136+
prefs.getStringSet(FLUTTER_IMAGE_PICKER_IMAGE_PATH_KEY, null);
137+
if (imagePathList != null) {
138+
pathList.addAll(imagePathList);
139+
resultMap.put(MAP_KEY_PATH_LIST, pathList);
140+
hasData = true;
141+
}
130142
}
131143

132144
if (prefs.contains(SHARED_PREFERENCE_ERROR_CODE_KEY)) {
@@ -159,7 +171,6 @@ Map<String, Object> getCacheMap() {
159171
resultMap.put(MAP_KEY_IMAGE_QUALITY, 100);
160172
}
161173
}
162-
163174
return resultMap;
164175
}
165176
}

packages/image_picker/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -217,17 +217,21 @@ void saveStateBeforeResult() {
217217

218218
void retrieveLostImage(MethodChannel.Result result) {
219219
Map<String, Object> resultMap = cache.getCacheMap();
220-
String path = (String) resultMap.get(cache.MAP_KEY_PATH);
221-
if (path != null) {
222-
Double maxWidth = (Double) resultMap.get(cache.MAP_KEY_MAX_WIDTH);
223-
Double maxHeight = (Double) resultMap.get(cache.MAP_KEY_MAX_HEIGHT);
224-
int imageQuality =
225-
resultMap.get(cache.MAP_KEY_IMAGE_QUALITY) == null
226-
? 100
227-
: (int) resultMap.get(cache.MAP_KEY_IMAGE_QUALITY);
228-
229-
String newPath = imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality);
230-
resultMap.put(cache.MAP_KEY_PATH, newPath);
220+
ArrayList<String> pathList = (ArrayList<String>) resultMap.get(cache.MAP_KEY_PATH_LIST);
221+
ArrayList<String> newPathList = new ArrayList<>();
222+
if (pathList != null) {
223+
for (String path : pathList) {
224+
Double maxWidth = (Double) resultMap.get(cache.MAP_KEY_MAX_WIDTH);
225+
Double maxHeight = (Double) resultMap.get(cache.MAP_KEY_MAX_HEIGHT);
226+
int imageQuality =
227+
resultMap.get(cache.MAP_KEY_IMAGE_QUALITY) == null
228+
? 100
229+
: (int) resultMap.get(cache.MAP_KEY_IMAGE_QUALITY);
230+
231+
newPathList.add(imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality));
232+
}
233+
resultMap.put(cache.MAP_KEY_PATH_LIST, newPathList);
234+
resultMap.put(cache.MAP_KEY_PATH, newPathList.get(newPathList.size() - 1));
231235
}
232236
if (resultMap.isEmpty()) {
233237
result.success(null);
@@ -558,6 +562,7 @@ public void onPathReady(String path) {
558562
private void handleMultiImageResult(
559563
ArrayList<String> paths, boolean shouldDeleteOriginalIfScaled) {
560564
if (methodCall != null) {
565+
ArrayList<String> finalPath = new ArrayList<>();
561566
for (int i = 0; i < paths.size(); i++) {
562567
String finalImagePath = getResizedImagePath(paths.get(i));
563568

@@ -567,8 +572,10 @@ private void handleMultiImageResult(
567572
&& shouldDeleteOriginalIfScaled) {
568573
new File(paths.get(i)).delete();
569574
}
570-
paths.set(i, finalImagePath);
575+
finalPath.add(i, finalImagePath);
571576
}
577+
finishWithListSuccess(finalPath);
578+
} else {
572579
finishWithListSuccess(paths);
573580
}
574581
}
@@ -615,7 +622,9 @@ private boolean setPendingMethodCallAndResult(
615622

616623
private void finishWithSuccess(String imagePath) {
617624
if (pendingResult == null) {
618-
cache.saveResult(imagePath, null, null);
625+
ArrayList<String> pathList = new ArrayList<>();
626+
pathList.add(imagePath);
627+
cache.saveResult(pathList, null, null);
619628
return;
620629
}
621630
pendingResult.success(imagePath);
@@ -624,9 +633,7 @@ private void finishWithSuccess(String imagePath) {
624633

625634
private void finishWithListSuccess(ArrayList<String> imagePaths) {
626635
if (pendingResult == null) {
627-
for (String imagePath : imagePaths) {
628-
cache.saveResult(imagePath, null, null);
629-
}
636+
cache.saveResult(imagePaths, null, null);
630637
return;
631638
}
632639
pendingResult.success(imagePaths);

packages/image_picker/image_picker/android/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
package io.flutter.plugins.imagepicker;
66

77
import static org.hamcrest.core.IsEqual.equalTo;
8+
import static org.junit.Assert.assertEquals;
89
import static org.junit.Assert.assertThat;
910
import static org.mockito.ArgumentMatchers.any;
1011
import static org.mockito.ArgumentMatchers.anyInt;
1112
import static org.mockito.ArgumentMatchers.eq;
13+
import static org.mockito.Mockito.doNothing;
1214
import static org.mockito.Mockito.doThrow;
1315
import static org.mockito.Mockito.mock;
1416
import static org.mockito.Mockito.times;
@@ -26,9 +28,13 @@
2628
import io.flutter.plugin.common.MethodCall;
2729
import io.flutter.plugin.common.MethodChannel;
2830
import java.io.File;
31+
import java.util.ArrayList;
32+
import java.util.HashMap;
33+
import java.util.Map;
2934
import org.junit.After;
3035
import org.junit.Before;
3136
import org.junit.Test;
37+
import org.mockito.ArgumentCaptor;
3238
import org.mockito.Mock;
3339
import org.mockito.MockedStatic;
3440
import org.mockito.Mockito;
@@ -368,6 +374,34 @@ public void onActivityResult_WhenImageTakenWithCamera_AndNoResizeNeeded_Finishes
368374
verifyNoMoreInteractions(mockResult);
369375
}
370376

377+
@Test
378+
public void
379+
retrieveLostImage_ShouldBeAbleToReturnLastItemFromResultMapWhenSingleFileIsRecovered() {
380+
Map<String, Object> resultMap = new HashMap<>();
381+
ArrayList<String> pathList = new ArrayList<>();
382+
pathList.add("/example/first_item");
383+
pathList.add("/example/last_item");
384+
resultMap.put("pathList", pathList);
385+
386+
when(mockImageResizer.resizeImageIfNeeded(pathList.get(0), null, null, 100))
387+
.thenReturn(pathList.get(0));
388+
when(mockImageResizer.resizeImageIfNeeded(pathList.get(1), null, null, 100))
389+
.thenReturn(pathList.get(1));
390+
when(cache.getCacheMap()).thenReturn(resultMap);
391+
392+
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
393+
394+
ImagePickerDelegate mockDelegate = createDelegate();
395+
396+
ArgumentCaptor<Map<String, Object>> valueCapture = ArgumentCaptor.forClass(Map.class);
397+
398+
doNothing().when(mockResult).success(valueCapture.capture());
399+
400+
mockDelegate.retrieveLostImage(mockResult);
401+
402+
assertEquals("/example/last_item", valueCapture.getValue().get("path"));
403+
}
404+
371405
private ImagePickerDelegate createDelegate() {
372406
return new ImagePickerDelegate(
373407
mockActivity,

packages/image_picker/image_picker/example/lib/main.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class _MyHomePageState extends State<MyHomePage> {
226226
isVideo = false;
227227
setState(() {
228228
_imageFile = response.file;
229+
_imageFileList = response.files;
229230
});
230231
}
231232
} else {

packages/image_picker/image_picker/pubspec.yaml

Lines changed: 2 additions & 2 deletions
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/plugins/tree/master/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.3+3
6+
version: 0.8.4
77

88
environment:
99
sdk: ">=2.12.0 <3.0.0"
@@ -25,7 +25,7 @@ dependencies:
2525
sdk: flutter
2626
flutter_plugin_android_lifecycle: ^2.0.1
2727
image_picker_for_web: ^2.1.0
28-
image_picker_platform_interface: ^2.2.0
28+
image_picker_platform_interface: ^2.3.0
2929

3030
dev_dependencies:
3131
flutter_test:

packages/image_picker/image_picker/test/image_picker_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,24 @@ void main() {
315315
expect(response.file!.path, '/example/path');
316316
});
317317

318+
test('retrieveLostData should successfully retrieve multiple files',
319+
() async {
320+
channel.setMockMethodCallHandler((MethodCall methodCall) async {
321+
return <String, dynamic>{
322+
'type': 'image',
323+
'path': '/example/path1',
324+
'pathList': ['/example/path0', '/example/path1'],
325+
};
326+
});
327+
328+
final LostDataResponse response = await picker.retrieveLostData();
329+
expect(response.type, RetrieveType.image);
330+
expect(response.file, isNotNull);
331+
expect(response.file!.path, '/example/path1');
332+
expect(response.files!.first.path, '/example/path0');
333+
expect(response.files!.length, 2);
334+
});
335+
318336
test('retrieveLostData get error response', () async {
319337
channel.setMockMethodCallHandler((MethodCall methodCall) async {
320338
return <String, String>{

packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ class MethodChannelImagePicker extends ImagePickerPlatform {
259259
final pathList = result['pathList'];
260260
if (pathList != null) {
261261
pickedFileList = [];
262-
// In this case, multiRetrieve is invoked.
263262
for (String path in pathList) {
264263
pickedFileList.add(XFile(path));
265264
}

0 commit comments

Comments
 (0)