[image_picker]fix a crash when a non-image file is picked. (#2293)

diff --git a/packages/image_picker/CHANGELOG.md b/packages/image_picker/CHANGELOG.md
index 11c48e8..96bb4fc 100644
--- a/packages/image_picker/CHANGELOG.md
+++ b/packages/image_picker/CHANGELOG.md
@@ -1,6 +1,11 @@
+## 0.6.2+1
+
+* Android: Fix a crash when a non-image file is picked.
+* Android: Fix unwanted bitmap scaling.
+
 ## 0.6.2
 
-* iOS: Fixes an issue where picking conent from Gallery would result in a crash on iOS 13.
+* iOS: Fixes an issue where picking content from Gallery would result in a crash on iOS 13.
 
 ## 0.6.1+11
 
diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java
index f9318e9..e34a3b5 100644
--- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java
+++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImagePickerDelegate.java
@@ -521,10 +521,7 @@
     if (methodCall != null) {
       Double maxWidth = methodCall.argument("maxWidth");
       Double maxHeight = methodCall.argument("maxHeight");
-      int imageQuality =
-          methodCall.argument("imageQuality") == null
-              ? 100
-              : (int) methodCall.argument("imageQuality");
+      Integer imageQuality = methodCall.argument("imageQuality");
 
       String finalImagePath =
           imageResizer.resizeImageIfNeeded(path, maxWidth, maxHeight, imageQuality);
diff --git a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java
index ab3120a..ca0498b 100644
--- a/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java
+++ b/packages/image_picker/android/src/main/java/io/flutter/plugins/imagepicker/ImageResizer.java
@@ -7,6 +7,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.util.Log;
+import androidx.annotation.Nullable;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -28,31 +29,39 @@
    * <p>If no resizing is needed, returns the path for the original image.
    */
   String resizeImageIfNeeded(
-      String imagePath, Double maxWidth, Double maxHeight, int imageQuality) {
+      String imagePath,
+      @Nullable Double maxWidth,
+      @Nullable Double maxHeight,
+      @Nullable Integer imageQuality) {
     boolean shouldScale =
-        maxWidth != null || maxHeight != null || (imageQuality > -1 && imageQuality < 101);
-
-    if (!shouldScale) {
-      return imagePath;
+        maxWidth != null || maxHeight != null || isImageQualityValid(imageQuality);
+    String[] pathParts = imagePath.split("/");
+    String imageName = pathParts[pathParts.length - 1];
+    File file;
+    Bitmap bmp = decodeFile(imagePath);
+    if (bmp == null) {
+      return null;
     }
-
     try {
-      File scaledImage = resizedImage(imagePath, maxWidth, maxHeight, imageQuality);
-      exifDataCopier.copyExif(imagePath, scaledImage.getPath());
-
-      return scaledImage.getPath();
+      if (!shouldScale) {
+        file = createImageOnExternalDirectory(imageName, bmp, 100);
+      } else {
+        file = resizedImage(bmp, maxWidth, maxHeight, imageQuality, imageName);
+      }
+      copyExif(imagePath, file.getPath());
+      return file.getPath();
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
   }
 
-  private File resizedImage(String path, Double maxWidth, Double maxHeight, int imageQuality)
+  private File resizedImage(
+      Bitmap bmp, Double maxWidth, Double maxHeight, Integer imageQuality, String outputImageName)
       throws IOException {
-    Bitmap bmp = BitmapFactory.decodeFile(path);
     double originalWidth = bmp.getWidth() * 1.0;
     double originalHeight = bmp.getHeight() * 1.0;
 
-    if (imageQuality < 0 || imageQuality > 100) {
+    if (!isImageQualityValid(imageQuality)) {
       imageQuality = 100;
     }
 
@@ -91,24 +100,51 @@
       }
     }
 
-    Bitmap scaledBmp = Bitmap.createScaledBitmap(bmp, width.intValue(), height.intValue(), false);
+    Bitmap scaledBmp = createScaledBitmap(bmp, width.intValue(), height.intValue(), false);
+    File file =
+        createImageOnExternalDirectory("/scaled_" + outputImageName, scaledBmp, imageQuality);
+    return file;
+  }
+
+  private File createFile(File externalFilesDirectory, String child) {
+    return new File(externalFilesDirectory, child);
+  }
+
+  private FileOutputStream createOutputStream(File imageFile) throws IOException {
+    return new FileOutputStream(imageFile);
+  }
+
+  private void copyExif(String filePathOri, String filePathDest) {
+    exifDataCopier.copyExif(filePathOri, filePathDest);
+  }
+
+  private Bitmap decodeFile(String path) {
+    return BitmapFactory.decodeFile(path);
+  }
+
+  private Bitmap createScaledBitmap(Bitmap bmp, int width, int height, boolean filter) {
+    return Bitmap.createScaledBitmap(bmp, width, height, filter);
+  }
+
+  private boolean isImageQualityValid(Integer imageQuality) {
+    return imageQuality != null && imageQuality > 0 && imageQuality < 100;
+  }
+
+  private File createImageOnExternalDirectory(String name, Bitmap bitmap, int imageQuality)
+      throws IOException {
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-    boolean saveAsPNG = bmp.hasAlpha();
+    boolean saveAsPNG = bitmap.hasAlpha();
     if (saveAsPNG) {
       Log.d(
           "ImageResizer",
           "image_picker: compressing is not supported for type PNG. Returning the image with original quality");
     }
-    scaledBmp.compress(
+    bitmap.compress(
         saveAsPNG ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG,
         imageQuality,
         outputStream);
-
-    String[] pathParts = path.split("/");
-    String imageName = pathParts[pathParts.length - 1];
-
-    File imageFile = new File(externalFilesDirectory, "/scaled_" + imageName);
-    FileOutputStream fileOutput = new FileOutputStream(imageFile);
+    File imageFile = createFile(externalFilesDirectory, name);
+    FileOutputStream fileOutput = createOutputStream(imageFile);
     fileOutput.write(outputStream.toByteArray());
     fileOutput.close();
     return imageFile;
diff --git a/packages/image_picker/example/android/app/build.gradle b/packages/image_picker/example/android/app/build.gradle
index 800e3e8..483268f 100755
--- a/packages/image_picker/example/android/app/build.gradle
+++ b/packages/image_picker/example/android/app/build.gradle
@@ -62,4 +62,5 @@
     testImplementation 'org.mockito:mockito-core:2.17.0'
     androidTestImplementation 'androidx.test:runner:1.1.1'
     androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+    testImplementation "org.robolectric:robolectric:3.3.2"
 }
diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java
index 8e89a15..51733a5 100644
--- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java
+++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerCacheTest.java
@@ -25,10 +25,7 @@
 import org.mockito.MockitoAnnotations;
 
 public class ImagePickerCacheTest {
-  private static final double WIDTH = 10.0;
-  private static final double HEIGHT = 10.0;
   private static final int IMAGE_QUALITY = 90;
-  private static final String PATH = "a_mock_path";
 
   @Mock Activity mockActivity;
   @Mock SharedPreferences mockPreference;
diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java
index 60e1167..88fa337 100644
--- a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java
+++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImagePickerDelegateTest.java
@@ -24,9 +24,9 @@
 import org.mockito.MockitoAnnotations;
 
 public class ImagePickerDelegateTest {
-  private static final double WIDTH = 10.0;
-  private static final double HEIGHT = 10.0;
-  private static final int IMAGE_QUALITY = 100;
+  private static final Double WIDTH = 10.0;
+  private static final Double HEIGHT = 10.0;
+  private static final Integer IMAGE_QUALITY = 90;
 
   @Mock Activity mockActivity;
   @Mock ImageResizer mockImageResizer;
@@ -62,13 +62,15 @@
     when(mockFileUtils.getPathFromUri(any(Context.class), any(Uri.class)))
         .thenReturn("pathFromUri");
 
+    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, null))
+        .thenReturn("originalPath");
     when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, null, IMAGE_QUALITY))
         .thenReturn("originalPath");
-    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, IMAGE_QUALITY))
+    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, HEIGHT, null))
         .thenReturn("scaledPath");
-    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, IMAGE_QUALITY))
+    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", WIDTH, null, null))
         .thenReturn("scaledPath");
-    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, IMAGE_QUALITY))
+    when(mockImageResizer.resizeImageIfNeeded("pathFromUri", null, HEIGHT, null))
         .thenReturn("scaledPath");
 
     mockFileUriResolver = new MockFileUriResolver();
diff --git a/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java
new file mode 100644
index 0000000..aac7472
--- /dev/null
+++ b/packages/image_picker/example/android/app/src/test/java/io/flutter/plugins/imagepicker/ImageResizerTest.java
@@ -0,0 +1,65 @@
+// Copyright 2019 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.imagepicker;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import java.io.File;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+
+// RobolectricTestRunner always creates a default mock bitmap when reading from file. So we cannot actually test the scaling.
+// But we can still test whether the original or scaled file is created.
+@RunWith(RobolectricTestRunner.class)
+public class ImageResizerTest {
+
+  ImageResizer resizer;
+  File imageFile;
+  File externalDirectory;
+  Bitmap originalImageBitmap;
+
+  @Before
+  public void setUp() throws IOException {
+    MockitoAnnotations.initMocks(this);
+    imageFile = new File(getClass().getClassLoader().getResource("pngImage.png").getFile());
+    originalImageBitmap = BitmapFactory.decodeFile(imageFile.getPath());
+    TemporaryFolder temporaryFolder = new TemporaryFolder();
+    temporaryFolder.create();
+    externalDirectory = temporaryFolder.newFolder("image_picker_testing_path");
+    resizer = new ImageResizer(externalDirectory, new ExifDataCopier());
+  }
+
+  @Test
+  public void onResizeImageIfNeeded_WhenQualityIsNull_ShoultNotResize_ReturnTheUnscaledFile() {
+    String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, null);
+    assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/pngImage.png"));
+  }
+
+  @Test
+  public void onResizeImageIfNeeded_WhenQualityIsNotNull_ShoulResize_ReturnResizedFile() {
+    String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, null, 50);
+    assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png"));
+  }
+
+  @Test
+  public void onResizeImageIfNeeded_WhenWidthIsNotNull_ShoulResize_ReturnResizedFile() {
+    String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), 50.0, null, null);
+    assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png"));
+  }
+
+  @Test
+  public void onResizeImageIfNeeded_WhenHeightIsNotNull_ShoulResize_ReturnResizedFile() {
+    String outoutFile = resizer.resizeImageIfNeeded(imageFile.getPath(), null, 50.0, null);
+    assertThat(outoutFile, equalTo(externalDirectory.getPath() + "/scaled_pngImage.png"));
+  }
+}
diff --git a/packages/image_picker/example/android/app/src/test/resources/pngImage.png b/packages/image_picker/example/android/app/src/test/resources/pngImage.png
new file mode 100644
index 0000000..22ac5a5
--- /dev/null
+++ b/packages/image_picker/example/android/app/src/test/resources/pngImage.png
Binary files differ
diff --git a/packages/image_picker/pubspec.yaml b/packages/image_picker/pubspec.yaml
index bca5a9d..0e47c53 100755
--- a/packages/image_picker/pubspec.yaml
+++ b/packages/image_picker/pubspec.yaml
@@ -5,7 +5,7 @@
   - Flutter Team <flutter-dev@googlegroups.com>
   - Rhodes Davis Jr. <rody.davis.jr@gmail.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/image_picker
-version: 0.6.2
+version: 0.6.2+1
 
 flutter:
   plugin: