Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/fix-dialog-android-filters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
dialog: patch
dialog-js: patch
---

Fixed an issue that caused the file picker not to open on Android when extension filters were set.
62 changes: 18 additions & 44 deletions plugins/dialog/android/src/main/java/DialogPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,18 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
try {
val args = invoke.parseArgs(FilePickerOptions::class.java)
val parsedTypes = parseFiltersOption(args.filters)

val intent = if (parsedTypes.isNotEmpty()) {
val intent = Intent(Intent.ACTION_PICK)
setIntentMimeTypes(intent, parsedTypes)
intent
} else {
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
intent

// TODO: ACTION_OPEN_DOCUMENT ??
val intent = Intent(Intent.ACTION_GET_CONTENT)
Comment on lines +60 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the docs I read about were using ACTION_OPEN_DOCUMENT, and https://developer.android.com/guide/components/intents-common#GetFile seems to suggest that EXTRA_MIME_TYPES is not available for ACTION_GET_CONTENT, but from testing it does work

And seems like if I use ACTION_OPEN_DOCUMENT, I'll be limited to just the files, but with ACTION_GET_CONTENT I can pick files from other apps (so I would probably prefer ACTION_GET_CONTENT as the one you're currently using)

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc (already forget 4 days later) other similar frameworks use open_document instead as well. One thing that seems like a major advantage of open_document is that is opens them in-place without copying them into your app cache or whatever. so i guess offering it as an option (after more investigation) sounds valuable to me.

And seems like if I use ACTION_OPEN_DOCUMENT, I'll be limited to just the files

not sure what you mean

it seems like we should almost always prefer it over ACTION_PICK

yep, action_pick only makes sense if we already have a list of data/files which i can't really think of a usecase for here

Copy link
Contributor

@Legend-Master Legend-Master Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure what you mean

This is with ACTION_OPEN_DOCUMENT (there's no side bar available and you can't choose files from Photos for example)

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah got it. i guess that makes sense though with how it opens files without copying them. hard to do if the file may be in the cloud.

intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"

if (parsedTypes.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
}

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, args.multiple ?: false)

startActivityForResult(invoke, intent, "filePickerResult")
} catch (ex: Exception) {
val message = ex.message ?: "Failed to pick file"
Expand Down Expand Up @@ -115,7 +113,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
callResult.put("files", JSArray.from(uris.toTypedArray()))
return callResult
}

private fun parseFiltersOption(filters: Array<Filter>): Array<String> {
val mimeTypes = mutableListOf<String>()
for (filter in filters) {
Expand All @@ -132,38 +130,10 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
return mimeTypes.toTypedArray()
}

private fun setIntentMimeTypes(intent: Intent, mimeTypes: Array<String>) {
if (mimeTypes.isNotEmpty()) {
var uniqueMimeKind = true
var mimeKind: String? = null
for (mime in mimeTypes) {
val kind = mime.split("/")[0]
if (mimeKind == null) {
mimeKind = kind
} else if (mimeKind != kind) {
uniqueMimeKind = false
}
}

if (uniqueMimeKind) {
if (mimeTypes.size > 1) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
intent.type = Intent.normalizeMimeType("$mimeKind/*")
} else {
intent.type = mimeTypes[0]
}
} else {
intent.type = "*/*"
}
} else {
intent.type = "*/*"
}
}

@Command
fun showMessageDialog(invoke: Invoke) {
val args = invoke.parseArgs(MessageOptions::class.java)

if (activity.isFinishing) {
invoke.reject("App is finishing")
return
Expand All @@ -179,7 +149,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
Handler(Looper.getMainLooper())
.post {
val builder = AlertDialog.Builder(activity)

if (args.title != null) {
builder.setTitle(args.title)
}
Expand Down Expand Up @@ -213,10 +183,14 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
val parsedTypes = parseFiltersOption(args.filters)

val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
setIntentMimeTypes(intent, parsedTypes)

intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.putExtra(Intent.EXTRA_TITLE, args.fileName ?: "")
intent.type = "*/*"

if (parsedTypes.isNotEmpty()) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
}

startActivityForResult(invoke, intent, "saveFileDialogResult")
} catch (ex: Exception) {
val message = ex.message ?: "Failed to pick save file"
Expand Down