diff --git a/packages/image_picker/image_picker_android/CHANGELOG.md b/packages/image_picker/image_picker_android/CHANGELOG.md index 5e382f8bfcf2..08cd9acf3dc1 100644 --- a/packages/image_picker/image_picker_android/CHANGELOG.md +++ b/packages/image_picker/image_picker_android/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.8.13+22 + +* Fixes a crash when the content provider returns no stream for a picked + image; the pick now fails with `missing_valid_image_uri` instead. + ## 0.8.13+21 * Updates pigeon dev_dependency to ^27.3.2 for analyzer 14 compatibility. diff --git a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java index d83f6fe7ec23..39274a1b5293 100644 --- a/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java +++ b/packages/image_picker/image_picker_android/android/src/main/java/io/flutter/plugins/imagepicker/FileUtils.java @@ -61,6 +61,13 @@ class FileUtils { */ String getPathFromUri(final Context context, final Uri uri) { try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { + if (inputStream == null) { + // `ContentResolver#openInputStream()` returns null when the provider cannot serve the + // item (for example after the provider crashed, or for a cloud-only photo it could not + // fetch). Treat it like any other unreadable item: no path, so the caller reports + // `missing_valid_image_uri` instead of crashing on the null stream. + return null; + } String uuid = UUID.randomUUID().toString(); File targetDirectory = new File(context.getCacheDir(), uuid); targetDirectory.mkdir(); diff --git a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/FileUtilTest.java b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/FileUtilTest.java index c0007be4ede6..27f6dd7ac5e0 100644 --- a/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/FileUtilTest.java +++ b/packages/image_picker/image_picker_android/android/src/test/java/io/flutter/plugins/imagepicker/FileUtilTest.java @@ -84,6 +84,23 @@ public void FileUtil_GetPathFromUri() throws IOException { assertEquals("imageStream", imageStream); } + @Test + public void FileUtil_GetPathFromUri_nullStream() throws IOException { + Uri uri = Uri.parse("content://dummy/dummy.png"); + + // `openInputStream` returns null when the provider cannot serve the item; this used to + // reach `copy()` and crash the plugin's executor thread with a NullPointerException. + ContentResolver mockContentResolver = mock(ContentResolver.class); + when(mockContentResolver.openInputStream(any(Uri.class))).thenReturn(null); + + Context mockContext = mock(Context.class); + when(mockContext.getContentResolver()).thenReturn(mockContentResolver); + + String path = fileUtils.getPathFromUri(mockContext, uri); + + assertNull(path); + } + @Test public void FileUtil_GetPathFromUri_securityException() throws IOException { Uri uri = Uri.parse("content://dummy/dummy.png"); diff --git a/packages/image_picker/image_picker_android/pubspec.yaml b/packages/image_picker/image_picker_android/pubspec.yaml index 5ac93f4d68ba..562b1315ecab 100755 --- a/packages/image_picker/image_picker_android/pubspec.yaml +++ b/packages/image_picker/image_picker_android/pubspec.yaml @@ -2,7 +2,7 @@ name: image_picker_android description: Android implementation of the image_picker plugin. repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.13+21 +version: 0.8.13+22 environment: sdk: ^3.12.0