Android Dark Mode Fix in Tauri: A Debugging War Story

Apr 8, 2026 · 6 min read

TauriAndroidRustJavaScriptDebugging

For weeks, the native Android status bar and navigation bar refused to update when toggling dark mode in a Tauri app. The JS code called the right function. The Rust handler logged the invocation. But the bars stayed stubbornly light.

Here's how I finally fixed it.

The Broken Bridge

The intended flow was clean: JavaScript calls invoke('plugin:theme|set_theme', { isDark }), which routes through Rust's Tauri plugin system, which calls into Kotlin to update the system bars.

Except the Kotlin ThemePlugin was never reached. Zero logcat output. Zero effect. The Rust-side plugin simply didn't exist — there was no handler registered to bridge the call to Android.

The Fix: Skip Rust Entirely

Instead of fixing the plugin chain, I bypassed the Rust layer entirely. Using a @JavascriptInterface annotated class injected directly into the WebView via onWebViewCreate():

Then in the Android setup:

Now JavaScript calls window.ThemeBridge.setTheme(isDark) directly — no Rust intermediary, no plugin chain, no silent failures.

The Lesson

Three weeks of debugging a broken abstraction. The fix was removing an unnecessary layer. It's a reminder that sometimes the most robust solution isn't fixing the bridge — it's asking whether the bridge should exist at all.