diff --git a/node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java b/node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java index 48fb5c1..3def244 100644 --- a/node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java +++ b/node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java @@ -3,6 +3,7 @@ package com.imagepicker; import android.Manifest; import android.app.Activity; import android.content.ActivityNotFoundException; +import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -49,6 +50,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.util.List; +import java.util.ArrayList; import com.facebook.react.modules.core.PermissionListener; import com.facebook.react.modules.core.PermissionAwareActivity; @@ -69,6 +71,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule public static final int REQUEST_LAUNCH_IMAGE_LIBRARY = 13002; public static final int REQUEST_LAUNCH_VIDEO_LIBRARY = 13003; public static final int REQUEST_LAUNCH_VIDEO_CAPTURE = 13004; + public static final int REQUEST_LAUNCH_MIXED_CAPTURE = 13005; public static final int REQUEST_PERMISSIONS_FOR_CAMERA = 14001; public static final int REQUEST_PERMISSIONS_FOR_LIBRARY = 14002; @@ -266,26 +269,24 @@ public class ImagePickerModule extends ReactContextBaseJavaModule cameraIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, videoDurationLimit); } } + else if (pickBoth) { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + this.setImageCaptureUri(takePictureIntent); + Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); + cameraIntent = new Intent(Intent.ACTION_CHOOSER); + Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); + Intent[] intentArray = new Intent[]{takePictureIntent,takeVideoIntent}; + cameraIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); + cameraIntent.putExtra(Intent.EXTRA_TITLE, "Choose an action"); + cameraIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); + requestCode = REQUEST_LAUNCH_MIXED_CAPTURE; + } else { requestCode = REQUEST_LAUNCH_IMAGE_CAPTURE; cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - final File original = createNewFile(reactContext, this.options, false); - imageConfig = imageConfig.withOriginalFile(original); - - if (imageConfig.original != null) { - cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original); - }else { - responseHelper.invokeError(callback, "Couldn't get file path for photo"); - return; - } - if (cameraCaptureURI == null) - { - responseHelper.invokeError(callback, "Couldn't get file path for photo"); - return; - } - cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraCaptureURI); + this.setImageCaptureUri(cameraIntent); } if (cameraIntent.resolveActivity(reactContext.getPackageManager()) == null) @@ -350,16 +351,19 @@ public class ImagePickerModule extends ReactContextBaseJavaModule libraryIntent = new Intent(Intent.ACTION_PICK); libraryIntent.setType("video/*"); } + else if (pickBoth) { + libraryIntent = new Intent(Intent.ACTION_GET_CONTENT); + libraryIntent.addCategory(Intent.CATEGORY_OPENABLE); + libraryIntent.setType("image/*"); + libraryIntent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"}); + requestCode = REQUEST_LAUNCH_MIXED_CAPTURE; + } else { requestCode = REQUEST_LAUNCH_IMAGE_LIBRARY; libraryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); - - if (pickBoth) - { - libraryIntent.setType("image/* video/*"); - } + libraryIntent.setType("image/*"); } if (libraryIntent.resolveActivity(reactContext.getPackageManager()) == null) @@ -385,75 +389,47 @@ public class ImagePickerModule extends ReactContextBaseJavaModule } } - @Override - public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { - //robustness code - if (passResult(requestCode)) - { - return; - } - - responseHelper.cleanResponse(); - - // user cancel - if (resultCode != Activity.RESULT_OK) - { - removeUselessFiles(requestCode, imageConfig); - responseHelper.invokeCancel(callback); - callback = null; - return; - } + protected String getMimeType(Activity activity, Uri uri) { + String mimeType = null; + if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) { + ContentResolver cr = activity.getApplicationContext().getContentResolver(); + mimeType = cr.getType(uri); + } else { + String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri + .toString()); + mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension( + fileExtension.toLowerCase()); + } + return mimeType; + } - Uri uri = null; - switch (requestCode) + protected void extractImageFromResult(Activity activity, Uri uri, int requestCode) { + String realPath = getRealPathFromURI(uri); + String mime = getMimeType(activity, uri); + final boolean isUrl = !TextUtils.isEmpty(realPath) && + Patterns.WEB_URL.matcher(realPath).matches(); + if (realPath == null || isUrl) { - case REQUEST_LAUNCH_IMAGE_CAPTURE: - uri = cameraCaptureURI; - break; - - case REQUEST_LAUNCH_IMAGE_LIBRARY: - uri = data.getData(); - String realPath = getRealPathFromURI(uri); - final boolean isUrl = !TextUtils.isEmpty(realPath) && - Patterns.WEB_URL.matcher(realPath).matches(); - if (realPath == null || isUrl) - { - try - { - File file = createFileFromURI(uri); - realPath = file.getAbsolutePath(); - uri = Uri.fromFile(file); - } - catch (Exception e) - { - // image not in cache - responseHelper.putString("error", "Could not read photo"); - responseHelper.putString("uri", uri.toString()); - responseHelper.invokeResponse(callback); - callback = null; - return; - } - } - imageConfig = imageConfig.withOriginalFile(new File(realPath)); - break; - - case REQUEST_LAUNCH_VIDEO_LIBRARY: - responseHelper.putString("uri", data.getData().toString()); - responseHelper.putString("path", getRealPathFromURI(data.getData())); - responseHelper.invokeResponse(callback); - callback = null; - return; - - case REQUEST_LAUNCH_VIDEO_CAPTURE: - final String path = getRealPathFromURI(data.getData()); - responseHelper.putString("uri", data.getData().toString()); - responseHelper.putString("path", path); - fileScan(reactContext, path); + try + { + File file = createFileFromURI(uri); + realPath = file.getAbsolutePath(); + uri = Uri.fromFile(file); + } + catch (Exception e) + { + // image not in cache + responseHelper.putString("error", "Could not read photo"); + responseHelper.putString("uri", uri.toString()); responseHelper.invokeResponse(callback); callback = null; + this.options = null; return; + } } + imageConfig = imageConfig.withOriginalFile(new File(realPath)); + final ReadExifResult result = readExifInterface(responseHelper, imageConfig); if (result.error != null) @@ -461,6 +437,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule removeUselessFiles(requestCode, imageConfig); responseHelper.invokeError(callback, result.error.getMessage()); callback = null; + this.options = null; return; } @@ -472,7 +449,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule updatedResultResponse(uri, imageConfig.original.getAbsolutePath()); // don't create a new file if contraint are respected - if (imageConfig.useOriginal(initialWidth, initialHeight, result.currentRotation)) + if (imageConfig.useOriginal(initialWidth, initialHeight, result.currentRotation) || mime.equals("image/gif")) { responseHelper.putInt("width", initialWidth); responseHelper.putInt("height", initialHeight); @@ -481,6 +458,14 @@ public class ImagePickerModule extends ReactContextBaseJavaModule else { imageConfig = getResizedImage(reactContext, this.options, imageConfig, initialWidth, initialHeight, requestCode); + if (imageConfig == null) + { + responseHelper.invokeError(callback, "Could not read image"); + callback = null; + this.options = null; + return; + } + if (imageConfig.resized == null) { removeUselessFiles(requestCode, imageConfig); @@ -523,6 +508,63 @@ public class ImagePickerModule extends ReactContextBaseJavaModule this.options = null; } + protected void extractVideoFromResult(Uri uri) { + responseHelper.putString("uri", uri.toString()); + responseHelper.putString("path", getRealPathFromURI(uri)); + responseHelper.invokeResponse(callback); + callback = null; + this.options = null; + } + + @Override + public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { + //robustness code + if (passResult(requestCode)) + { + return; + } + + responseHelper.cleanResponse(); + + // user cancel + if (resultCode != Activity.RESULT_OK) + { + removeUselessFiles(requestCode, imageConfig); + responseHelper.invokeCancel(callback); + callback = null; + return; + } + + switch (requestCode) + { + case REQUEST_LAUNCH_IMAGE_CAPTURE: + extractImageFromResult(activity, cameraCaptureURI, requestCode); + break; + + case REQUEST_LAUNCH_IMAGE_LIBRARY: + extractImageFromResult(activity, data.getData(), requestCode); + break; + + case REQUEST_LAUNCH_VIDEO_LIBRARY: + extractVideoFromResult(data.getData()); + break; + + case REQUEST_LAUNCH_MIXED_CAPTURE: + case REQUEST_LAUNCH_VIDEO_CAPTURE: + if (data == null || data.getData() == null) { + extractImageFromResult(activity, cameraCaptureURI, requestCode); + } else { + Uri selectedMediaUri = data.getData(); + if (selectedMediaUri.toString().contains("image")) { + extractImageFromResult(activity, selectedMediaUri, requestCode); + } else { + extractVideoFromResult(selectedMediaUri); + } + } + break; + } + } + public void invokeCustomButton(@NonNull final String action) { responseHelper.invokeCustomButton(this.callback, action); @@ -551,7 +593,8 @@ public class ImagePickerModule extends ReactContextBaseJavaModule { return callback == null || (cameraCaptureURI == null && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE) || (requestCode != REQUEST_LAUNCH_IMAGE_CAPTURE && requestCode != REQUEST_LAUNCH_IMAGE_LIBRARY - && requestCode != REQUEST_LAUNCH_VIDEO_LIBRARY && requestCode != REQUEST_LAUNCH_VIDEO_CAPTURE); + && requestCode != REQUEST_LAUNCH_VIDEO_LIBRARY && requestCode != REQUEST_LAUNCH_VIDEO_CAPTURE + && requestCode != REQUEST_LAUNCH_MIXED_CAPTURE); } private void updatedResultResponse(@Nullable final Uri uri, @@ -571,22 +614,23 @@ public class ImagePickerModule extends ReactContextBaseJavaModule @NonNull final Callback callback, @NonNull final int requestCode) { - final int writePermission = ActivityCompat - .checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); - final int cameraPermission = ActivityCompat - .checkSelfPermission(activity, Manifest.permission.CAMERA); - - boolean permissionsGranted = false; - + int selfCheckResult = 0; switch (requestCode) { case REQUEST_PERMISSIONS_FOR_LIBRARY: - permissionsGranted = writePermission == PackageManager.PERMISSION_GRANTED; + selfCheckResult = ActivityCompat + .checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); break; case REQUEST_PERMISSIONS_FOR_CAMERA: - permissionsGranted = cameraPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED; + selfCheckResult = ActivityCompat + .checkSelfPermission(activity, Manifest.permission.CAMERA); + if (selfCheckResult == PackageManager.PERMISSION_GRANTED) { + selfCheckResult = ActivityCompat + .checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); + } break; } + final boolean permissionsGranted = selfCheckResult == PackageManager.PERMISSION_GRANTED; if (!permissionsGranted) { final Boolean dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA); @@ -787,4 +831,22 @@ public class ImagePickerModule extends ReactContextBaseJavaModule videoDurationLimit = options.getInt("durationLimit"); } } + + private void setImageCaptureUri(Intent cameraIntent) { + final File original = createNewFile(reactContext, this.options, false); + imageConfig = imageConfig.withOriginalFile(original); + + if (imageConfig.original != null) { + cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original); + }else { + responseHelper.invokeError(callback, "Couldn't get file path for photo"); + return; + } + if (cameraCaptureURI == null) + { + responseHelper.invokeError(callback, "Couldn't get file path for photo"); + return; + } + cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraCaptureURI); + } }