From 7086e95f555bf61143837f3fa8cb4d8a83491b97 Mon Sep 17 00:00:00 2001 From: Johan du Toit Date: Thu, 7 Sep 2023 09:59:04 +0200 Subject: [PATCH] feat(android): orignal file path (#2209) BREAKING CHANGE: changed the way the name is retrieved --- README.md | 1 + .../src/main/java/com/imagepicker/Utils.java | 112 +++++++++++++----- 2 files changed, 82 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 24ceff402..1bd2b14d7 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ The `callback` will be called with a response object, refer to [The Response Obj | --------- | --- | ------- | --- | ----------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | base64 | OK | OK | OK | PHOTO ONLY | NO | The base64 string of the image (photos only) | | uri | OK | OK | OK | BOTH | NO | The file uri in app specific cache storage. Except when picking **video from Android gallery** where you will get read only content uri, to get file uri in this case copy the file to app specific storage using any react-native library. For web it uses the base64 as uri. | +| originalPath | NO | OK | NO | BOTH | NO | The original file path. | | width | OK | OK | OK | BOTH | NO | Asset dimensions | | height | OK | OK | OK | BOTH | NO | Asset dimensions | | fileSize | OK | OK | NO | BOTH | NO | The file size | diff --git a/android/src/main/java/com/imagepicker/Utils.java b/android/src/main/java/com/imagepicker/Utils.java index ab530f924..7a3710e34 100644 --- a/android/src/main/java/com/imagepicker/Utils.java +++ b/android/src/main/java/com/imagepicker/Utils.java @@ -32,7 +32,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -387,7 +386,7 @@ static String getMimeType(Uri uri, Context context) { String contentResolverMimeType = contentResolver.getType(uri); if (contentResolverMimeType.isBlank()) { - return getMimeTypeFromCursor(contentResolver, uri); + return getMimeTypeForContent(uri, context); } else { return contentResolverMimeType; } @@ -396,22 +395,65 @@ static String getMimeType(Uri uri, Context context) { return "Unknown"; } - static @Nullable String getMimeTypeFromCursor(ContentResolver contentResolver, Uri uri) { - Cursor cursor = contentResolver.query(uri, null, null, null, null); + static @Nullable String getMimeTypeForContent(Uri uri, Context context) { + String fileName = getFileNameForContent(uri, context); String fileType = "Unknown"; + + int lastDotIndex = fileName.lastIndexOf('.'); + if (lastDotIndex != -1) { + fileType = fileName.substring(lastDotIndex + 1); + } + return fileType; + } + + static String getFileName(Uri uri, Context context) { + if (uri.getScheme().equals("file")) { + return uri.getLastPathSegment(); + } else if (uri.getScheme().equals("content")) { + return getFileNameForContent(uri, context); + } + + return "Unknown"; + } + + static String getOriginalFilePath(Uri uri, Context context) { + String originPath; + if (uri.getScheme().contains("content")) { + originPath = getFilePathFromContent(uri, context); + uri = getAppSpecificStorageUri(uri, context); + } else { + originPath = uri.toString(); + } + + return originPath; + } + + private static String getFilePathFromContent(Uri uri, Context context) { + String[] proj = {MediaStore.Images.Media.DATA}; + try (Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null)) { + int index = cursor.getColumnIndex(MediaStore.Images.Media.DATA); + if (index == -1) { + return null; + } + cursor.moveToFirst(); + return cursor.getString(index); + } + } + + private static String getFileNameForContent(Uri uri, Context context) { + ContentResolver contentResolver = context.getContentResolver(); + Cursor cursor = contentResolver.query(uri, null, null, null, null); + + String fileName = uri.getLastPathSegment(); try { if (cursor.moveToFirst()) { int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME); - String fileName = cursor.getString(nameIndex); - int lastDotIndex = fileName.lastIndexOf('.'); - if (lastDotIndex != -1) { - fileType = fileName.substring(lastDotIndex + 1); - } + fileName = cursor.getString(nameIndex); } } finally { cursor.close(); } - return fileType; + return fileName; } static List collectUrisFromData(Intent data) { @@ -431,21 +473,24 @@ static List collectUrisFromData(Intent data) { return fileUris; } - static ReadableMap getImageResponseMap(Uri uri, Options options, Context context) { - String fileName = uri.getLastPathSegment(); - ImageMetadata imageMetadata = new ImageMetadata(uri, context); - int[] dimensions = getImageDimensions(uri, context); + static ReadableMap getImageResponseMap(Uri uri, Uri appSpecificUri, Options options, Context context) { + ImageMetadata imageMetadata = new ImageMetadata(appSpecificUri, context); + int[] dimensions = getImageDimensions(appSpecificUri, context); + + String fileName = getFileName(uri, context); + String originalPath = getOriginalFilePath(uri, context); WritableMap map = Arguments.createMap(); - map.putString("uri", uri.toString()); - map.putDouble("fileSize", getFileSize(uri, context)); + map.putString("uri", appSpecificUri.toString()); + map.putDouble("fileSize", getFileSize(appSpecificUri, context)); map.putString("fileName", fileName); map.putInt("width", dimensions[0]); map.putInt("height", dimensions[1]); - map.putString("type", getMimeType(uri, context)); + map.putString("type", getMimeType(appSpecificUri, context)); + map.putString("originalPath", originalPath); if (options.includeBase64) { - map.putString("base64", getBase64String(uri, context)); + map.putString("base64", getBase64String(appSpecificUri, context)); } if (options.includeExtra) { @@ -457,19 +502,22 @@ static ReadableMap getImageResponseMap(Uri uri, Options options, Context context return map; } - static ReadableMap getVideoResponseMap(Uri uri, Options options, Context context) { - String fileName = uri.getLastPathSegment(); + static ReadableMap getVideoResponseMap(Uri uri, Uri appSpecificUri,Options options, Context context) { WritableMap map = Arguments.createMap(); - VideoMetadata videoMetadata = new VideoMetadata(uri, context); + VideoMetadata videoMetadata = new VideoMetadata(appSpecificUri, context); - map.putString("uri", uri.toString()); - map.putDouble("fileSize", getFileSize(uri, context)); + String fileName = getFileName(uri, context); + String originalPath = getOriginalFilePath(uri, context); + + map.putString("uri", appSpecificUri.toString()); + map.putDouble("fileSize", getFileSize(appSpecificUri, context)); map.putInt("duration", videoMetadata.getDuration()); map.putInt("bitrate", videoMetadata.getBitrate()); map.putString("fileName", fileName); - map.putString("type", getMimeType(uri, context)); + map.putString("type", getMimeType(appSpecificUri, context)); map.putInt("width", videoMetadata.getWidth()); map.putInt("height", videoMetadata.getHeight()); + map.putString("originalPath", originalPath); if (options.includeExtra) { // Add more extra data here ... @@ -486,18 +534,20 @@ static ReadableMap getResponseMap(List fileUris, Options options, Context c for (int i = 0; i < fileUris.size(); ++i) { Uri uri = fileUris.get(i); + Uri appSpecificUrl = uri; + if (uri.getScheme().contains("content")) { + appSpecificUrl = getAppSpecificStorageUri(uri, context); + } + // Call getAppSpecificStorageUri in the if block to avoid copying unsupported files if (isImageType(uri, context)) { - if (uri.getScheme().contains("content")) { - uri = getAppSpecificStorageUri(uri, context); - } - uri = resizeImage(uri, context, options); - assets.pushMap(getImageResponseMap(uri, options, context)); + appSpecificUrl = resizeImage(appSpecificUrl, context, options); + assets.pushMap(getImageResponseMap(uri, appSpecificUrl, options, context)); } else if (isVideoType(uri, context)) { if (uri.getScheme().contains("content")) { - uri = getAppSpecificStorageUri(uri, context); + appSpecificUrl = getAppSpecificStorageUri(uri, context); } - assets.pushMap(getVideoResponseMap(uri, options, context)); + assets.pushMap(getVideoResponseMap(uri, appSpecificUrl, options, context)); } else { throw new RuntimeException("Unsupported file type"); }