Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fs] On Android I cannot extract filename returned by open / pick_file(s) #1775

Open
micouy opened this issue Sep 13, 2024 · 2 comments · May be fixed by #2421
Open

[fs] On Android I cannot extract filename returned by open / pick_file(s) #1775

micouy opened this issue Sep 13, 2024 · 2 comments · May be fixed by #2421
Labels
plugin: dialog plugin: fs Includes former "fs-extra" and "fs-watch" plugins question Further information is requested

Comments

@micouy
Copy link

micouy commented Sep 13, 2024

When I select files on Android (either by open on frontend or pick_files on backend) a content:// URI is returned:

content://com.android.providers.media.documents/document/image%3A18

How do I get to the filename? Should I use some resolver or open the file some other way?

@aiueo13
Copy link

aiueo13 commented Sep 17, 2024

Resolved? I'll make a temp plugin for you if you need it.

@FabianLars FabianLars added question Further information is requested plugin: dialog plugin: fs Includes former "fs-extra" and "fs-watch" plugins labels Sep 17, 2024
@micouy
Copy link
Author

micouy commented Sep 18, 2024

I got it partially working by fetching type and name while opening the file descriptor in FsPlugin.kt:

    fun getFileDescriptor(invoke: Invoke) {
        val args = invoke.parseArgs(GetFileDescriptorArgs::class.java)

        val res = JSObject()

        if (args.uri.startsWith(app.tauri.TAURI_ASSETS_DIRECTORY_URI)) {
            val path = args.uri.substring(app.tauri.TAURI_ASSETS_DIRECTORY_URI.length)
            try {
                val fd = activity.assets.openFd(path).parcelFileDescriptor?.detachFd()
                res.put("fd", fd)
                // Get MIME type
                // val mimeType =
                //
                // activity.contentResolver.getType(Uri.parse("file:///android_asset/$path"))
                val mimeType = activity.contentResolver.getType(Uri.parse(args.uri))
                res.put("mimeType", mimeType ?: "application/octet-stream")

                // Get file name
                val fileName = Uri.parse(args.uri).lastPathSegment
                res.put("fileName", fileName)
                res.put("branch", "uncompressed asset")
            } catch (e: IOException) {
                // if the asset is compressed, we cannot open a file descriptor directly
                // so we copy it to the cache and get a fd from there
                // this is a lot faster than serializing the file and sending it as invoke response
                // because on the Rust side we can leverage the custom protocol IPC and read the
                // file directly
                val cacheFile = File(activity.cacheDir, "_assets/$path")
                cacheFile.parentFile?.mkdirs()
                copyAsset(path, cacheFile)

                val fd =
                        ParcelFileDescriptor.open(
                                        cacheFile,
                                        ParcelFileDescriptor.parseMode(args.mode)
                                )
                                .detachFd()
                res.put("fd", fd)

                // Get MIME type
                val mimeType = activity.contentResolver.getType(Uri.fromFile(cacheFile))
                res.put("mimeType", mimeType ?: "application/octet-stream")

                // Get file name
                val fileName = Uri.fromFile(cacheFile).lastPathSegment
                res.put("fileName", fileName)
                res.put("branch", "compressed asset $e")
            }
        } else {
            val mimeType = activity.contentResolver.getType(Uri.parse(args.uri))
            val fileName =
                    activity.contentResolver.query(Uri.parse(args.uri), null, null, null, null)
                            ?.use { cursor ->
                                if (cursor.moveToFirst()) {
                                    val nameIndex =
                                            cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)

                                    if (nameIndex != -1) {
                                        cursor.getString(nameIndex)
                                    } else {
                                        null
                                    }
                                } else {
                                    null
                                }
                            }
                            ?: Uri.parse(args.uri).lastPathSegment
            val fd =
                    activity.contentResolver
                            .openAssetFileDescriptor(Uri.parse(args.uri), args.mode)
                            ?.parcelFileDescriptor
                            ?.detachFd()
            res.put("fd", fd)

            res.put("mimeType", mimeType)
            res.put("fileName", fileName)
            res.put("branch", "not asset")
        }

        invoke.resolve(res)
    }

However, I'm still interested if and when such functionality is going to be added to the plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: dialog plugin: fs Includes former "fs-extra" and "fs-watch" plugins question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants