Skip to content

feat(mobile): add file association support#14486

Merged
FabianLars merged 40 commits into
devfrom
feat/mobile-file-association
Apr 13, 2026
Merged

feat(mobile): add file association support#14486
FabianLars merged 40 commits into
devfrom
feat/mobile-file-association

Conversation

@lucasfernog

Copy link
Copy Markdown
Member

needs tauri-apps/tao#1155
needs tauri-apps/wry#1634

needs #14484 to be merged first

move the stdout/stderr forward logic to Swift so it does not consume a Rust thread and never deadlocks on the simulator

I had to work on this because i'm facing #12172 again on latest Xcode (26.1)
This reverts commit bfc74a7.
@lucasfernog lucasfernog requested a review from a team as a code owner November 17, 2025 15:24
@github-actions

github-actions Bot commented Nov 17, 2025

Copy link
Copy Markdown
Contributor

Package Changes Through 22e50d9

There are 11 changes which include tauri with minor, @tauri-apps/api with minor, tauri-macos-sign with patch, tauri-build with minor, tauri-runtime with minor, tauri-runtime-wry with minor, tauri-bundler with minor, tauri-cli with minor, @tauri-apps/cli with minor, tauri-utils with minor, tauri-plugin with minor

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
@tauri-apps/api 2.10.1 2.11.0
tauri-utils 2.8.3 2.9.0
tauri-macos-sign 2.3.3 2.3.4
tauri-bundler 2.8.1 2.9.0
tauri-runtime 2.10.1 2.11.0
tauri-runtime-wry 2.10.1 2.11.0
tauri-codegen 2.5.5 2.5.6
tauri-macros 2.5.5 2.5.6
tauri-plugin 2.5.4 2.6.0
tauri-build 2.5.6 2.6.0
tauri 2.10.3 2.11.0
@tauri-apps/cli 2.10.1 2.11.0
tauri-cli 2.10.1 2.11.0

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

filters
}

fn extension_to_mime_type(ext: &str) -> Option<String> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this covers ~25 file types it is important to include support for custom file extensions/MIME types.

We need to be able to define these in tauri.conf.json for desktop/mobile so they are available to the builder in order to generate correct platform-specific metadata e.g. info.plist, AndroidManifest.xml.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

these are just some default values because a mime type is required for the iOS file association to work; you can still define those manually in tauri.conf.json to support other types

let path_patterns: Vec<String> = association
.ext
.iter()
.map(|ext| format!(".*\\\\.{}", ext.0))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Android's pathPattern has known limitations e.g. Doesn't match paths with multiple dots (e.g., file.backup.png).

Workarounds:

  1. Use multiple patterns
<data android:pathPattern=".*\\.png" />
<data android:pathPattern=".*\\..*\\.png" />
<data android:pathPattern=".*\\..*\\..*\\.png" />
  1. Use MIME type only
<intent-filter>
    <action android:name="android.intent.action.SEND" />
    <data android:mimeType="image/png" />
    <!-- No pathPattern - rely on MIME type -->
</intent-filter>
  1. Scheme + MIME Type
<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="file" />
    <data android:scheme="content" />
    <data android:mimeType="image/png" />
</intent-filter

If filters are not generated properly, the only way forward is then to use a wildcard (*) filter which associates the app with all file/MIME types - this is not an ideal UX experience.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

this can be accomplished by just setting a mimeType in the file association config

filters.push_str(" <action android:name=\"android.intent.action.SEND\" />\n");
filters.push_str(" <action android:name=\"android.intent.action.SEND_MULTIPLE\" />\n");
filters.push_str(" <category android:name=\"android.intent.category.DEFAULT\" />\n");
filters.push_str(" <category android:name=\"android.intent.category.BROWSABLE\" />\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We are missing ACTION_VIEW e.g. user taps in file manager. Ideally, if would be good if we could define which actions we which to listen to.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

filters.push_str(" <action android:name=\"android.intent.action.SEND\" />\n");
filters.push_str(" <action android:name=\"android.intent.action.SEND_MULTIPLE\" />\n");
filters.push_str(" <category android:name=\"android.intent.category.DEFAULT\" />\n");
filters.push_str(" <category android:name=\"android.intent.category.BROWSABLE\" />\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From Android Docs:

BROWSABLE - The target activity allows itself to be started by a web browser to display data referenced by a link, such as an image or an e-mail message.

This is related to deep-linking not file association. Does this need to be handled differently? How will this interact with the deep-link plugin?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

the deep-link plugin will need a small change to actually detect that the intent contains a URL that was registered as a deep link - currently it always emits the event

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @lucasfernog. Is this task being tracked somewhere? Ensuring that both features continue to work together is an important requirement.

// If we have mime types, create intent filters
if !mime_types.is_empty() {
for mime_type in &mime_types {
filters.push_str("<intent-filter>\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Tauri config has rank but this is not being used on Android.

{
  "ext": ["png"],
  "mimeType": "image/png",
  "rank": "Owner"  // ← This exists in config
}

Android can specify a priority on intent filters which is a signed integer between -1000 to 1000.

<intent-filter android:priority="1000">
    <action android:name="android.intent.action.VIEW" />
    <data android:mimeType="image/png" />
</intent-filter>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

the priority is only related to other intent filters in the same app
rank is a macOS config that describes whether the app is the owner of a file type or just a secondary viewer.

}

/// Maps file extensions to their standard UTIs for macOS/iOS share sheet support
fn extension_to_uti(ext: &str) -> Option<&'static str> {

@velocitysystems velocitysystems Nov 26, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same content RE: file extensions and standard UTIs. While this covers ~30 file types it is important to include support for custom file extensions/MIME types in tauri.conf.json.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

content types can be defined in tauri.conf.json, this is just a fallback

Base automatically changed from feat/mobile-multi-window to dev March 23, 2026 16:32
@FabianLars FabianLars merged commit cc5c976 into dev Apr 13, 2026
34 of 35 checks passed
@FabianLars FabianLars deleted the feat/mobile-file-association branch April 13, 2026 17:41
lucasfernog added a commit to tauri-apps/tauri-docs that referenced this pull request Apr 14, 2026
razein97 pushed a commit to razein97/tauri that referenced this pull request Apr 30, 2026
razein97 pushed a commit to razein97/tauri that referenced this pull request Apr 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants