Tauri 2 Mobile Development
Build cross-platform mobile apps with Tauri 2 using web technologies (HTML/CSS/JS) for UI and Rust for native backend.
Quick Reference
Task Command
Init mobile npm run tauri android init / npm run tauri ios init
Dev Android npm run tauri android dev
Dev iOS npm run tauri ios dev
Build APK npm run tauri android build --apk
Build AAB npm run tauri android build --aab
Build iOS npm run tauri ios build
Add plugin npm run tauri add <plugin-name>
Workflow Decision Tree
New Project Setup
-
Read references/setup.md for environment configuration
-
Run npm create tauri-app@latest with mobile targets
-
Configure tauri.conf.json with app identifier
Adding Features
-
Native functionality: Read references/plugins.md
-
Rust commands/state: Read references/rust-patterns.md
-
Frontend integration: Read references/frontend-patterns.md
-
Authentication/OAuth: Read references/authentication.md
-
In-app purchases: Read references/iap.md
Testing
-
Emulator/ADB debug: Read references/testing.md
-
Use adb logcat | grep -iE "(tauri|RustStdout)" for logs
Building & Deployment
-
Code signing & stores: Read references/build-deploy.md
-
CI/CD pipelines: Read references/ci-cd.md
Project Structure
my-app/ ├── src/ # Frontend ├── src-tauri/ │ ├── Cargo.toml │ ├── tauri.conf.json # Main config │ ├── src/ │ │ ├── main.rs # Desktop entry (don't modify) │ │ └── lib.rs # Main code + mobile entry │ ├── capabilities/ │ │ └── default.json # Permissions │ └── gen/ │ ├── android/ # Android Studio project │ └── apple/ # Xcode project
Essential Configuration
tauri.conf.json
{ "$schema": "https://schema.tauri.app/config/2", "productName": "MyApp", "identifier": "com.company.myapp", "bundle": { "iOS": { "minimumSystemVersion": "14.0" }, "android": { "minSdkVersion": 24 } } }
capabilities/default.json
{ "identifier": "default", "windows": ["main"], "permissions": ["core:default"] }
lib.rs (Mobile Entry)
#[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_deep_link::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) .expect("error"); }
#[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}!", name) }
Common Issues
Problem Solution
White screen Check JS console, verify devUrl , check capabilities
iOS won't connect Use --force-ip-prompt , select IPv6
INSTALL_FAILED_ALREADY_EXISTS adb uninstall com.your.app
Emulator not detected Verify adb devices , restart ADB
HMR not working Configure vite.config.ts with TAURI_DEV_HOST
Shell plugin URL error Use opener plugin instead (openUrl() )
Google OAuth fails Google blocks WebView; use system browser flow
Deep link not received Check scheme in tauri.conf.json, init plugin
Safe area CSS fails on Android env() not supported in WebView; use JS fallback
Windows APK build symlink error Enable Developer Mode or copy .so files manually
Stale content after rebuild .so compiled in dev mode embeds old assets; rebuild with tauri android build --debug or apply Kotlin workaround (see build-deploy.md)
OpenSSL cross-compile fails on Windows Install Strawberry Perl for vendored OpenSSL; see build-deploy.md
See references/testing.md for detailed troubleshooting.
Resources
-
Docs: https://v2.tauri.app
-
Plugins: https://v2.tauri.app/plugin/