diff --git a/.changes/dialog-path-return-mismatch.md b/.changes/dialog-path-return-mismatch.md new file mode 100644 index 00000000..420170c9 --- /dev/null +++ b/.changes/dialog-path-return-mismatch.md @@ -0,0 +1,5 @@ +--- +"dialog": "patch" +--- + +Fixed an issue where dialogs on android would return the Content URI instead of the file path diff --git a/plugins/dialog/android/src/main/java/DialogPlugin.kt b/plugins/dialog/android/src/main/java/DialogPlugin.kt index 462e22bb..73eacfb6 100644 --- a/plugins/dialog/android/src/main/java/DialogPlugin.kt +++ b/plugins/dialog/android/src/main/java/DialogPlugin.kt @@ -141,7 +141,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) { fileResult.put("modifiedAt", modifiedAt) } fileResult.put("name", FilePickerUtils.getNameFromUri(activity, uri)) - fileResult.put("path", FilePickerUtils.getPathFromUri(uri)) + fileResult.put("path", FilePickerUtils.getPathFromUri(activity, uri)) fileResult.put("size", FilePickerUtils.getSizeFromUri(activity, uri)) filesResultList.add(fileResult) } diff --git a/plugins/dialog/android/src/main/java/FilePickerUtils.kt b/plugins/dialog/android/src/main/java/FilePickerUtils.kt index 5f0854a1..7029d4c6 100644 --- a/plugins/dialog/android/src/main/java/FilePickerUtils.kt +++ b/plugins/dialog/android/src/main/java/FilePickerUtils.kt @@ -4,10 +4,15 @@ package app.tauri.dialog + +import android.content.ContentUris +import android.database.Cursor +import android.provider.MediaStore import android.content.Context import android.graphics.BitmapFactory import android.media.MediaMetadataRetriever import android.net.Uri +import android.os.Environment import android.provider.DocumentsContract import android.provider.OpenableColumns import android.util.Base64 @@ -21,8 +26,40 @@ class FilePickerUtils { class FileResolution(var height: Int, var width: Int) companion object { - fun getPathFromUri(uri: Uri): String { - return uri.toString() + fun getPathFromUri(context: Context, uri: Uri): String? { + if (DocumentsContract.isDocumentUri(context, uri)) { + if (isExternalStorageDocument(uri)) { + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":") + return if ("primary".equals(split[0], ignoreCase = true)) { + "${Environment.getExternalStorageDirectory()}/${split[1]}" + } else { + null + } + } else if (isDownloadsDocument(uri)) { + val id = DocumentsContract.getDocumentId(uri) + val contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)) + return getDataColumn(context, contentUri, null, null) + } else if (isMediaDocument(uri)) { + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":") + val contentUri: Uri? = when (split[0]) { + "image" -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "video" -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI + "audio" -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + else -> null + } + val selection = "_id=?" + val selectionArgs = arrayOf(split[1]) + return getDataColumn(context, contentUri, selection, selectionArgs) + } + } else if ("content".equals(uri.scheme, ignoreCase = true)) { + return getDataColumn(context, uri, null, null) + } else if ("file".equals(uri.scheme, ignoreCase = true)) { + return uri.path + } + return null } fun getNameFromUri(context: Context, uri: Uri): String? { @@ -36,7 +73,7 @@ class FilePickerUtils { displayName = cursor.getString(columnIdx) cursor.close() } - if (displayName == null || displayName.isEmpty()) { + if (displayName.isNullOrEmpty()) { displayName = uri.lastPathSegment } return displayName @@ -162,4 +199,32 @@ class FilePickerUtils { return os.toByteArray() } } -} \ No newline at end of file +} + +private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array?): String? { + var cursor: Cursor? = null + val column = "_data" + val projection = arrayOf(column) + try { + cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null) + if (cursor != null && cursor.moveToFirst()) { + val columnIndex = cursor.getColumnIndexOrThrow(column) + return cursor.getString(columnIndex) + } + } finally { + cursor?.close() + } + return null +} + +private fun isExternalStorageDocument(uri: Uri): Boolean { + return "com.android.externalstorage.documents" == uri.authority +} + +private fun isDownloadsDocument(uri: Uri): Boolean { + return "com.android.providers.downloads.documents" == uri.authority +} + +private fun isMediaDocument(uri: Uri): Boolean { + return "com.android.providers.media.documents" == uri.authority +}