Skip to content

Commit a3dda29

Browse files
committed
docs: update wear os tauri blog post
1 parent 556dd9b commit a3dda29

1 file changed

Lines changed: 10 additions & 14 deletions

File tree

content/blog/2026-02-17-wear-os-tauri.md

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,12 @@ private fun handleOfflineSyncRequest() {
253253
}
254254
```
255255

256-
**Tier 3 — Offline writes:** When the watch sends a save or delete command and the plugin isn't loaded, a foreground service boots the Tauri runtime headlessly, waits for the plugin to initialize (~1 second), then replays the message through the normal path:
256+
**Tier 3 — Offline writes:** When the watch sends a save or delete command and the plugin isn't loaded, the message is first persisted to `WearSyncQueue`, then a foreground service boots the Tauri runtime headlessly. After the Kotlin `Channel` is registered and the app crate explicitly signals listener readiness, queued messages are drained and forwarded:
257257

258258
```kotlin
259-
private fun bootTauriAndReplay(path: String, data: String) {
259+
private fun bootTauriAndProcessQueue(path: String, data: String) {
260+
WearSyncQueue.enqueue(this, path, data)
261+
260262
scope.launch {
261263
// Launch the main activity silently to boot Tauri
262264
val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
@@ -265,21 +267,15 @@ private fun bootTauriAndReplay(path: String, data: String) {
265267
)
266268
startActivity(launchIntent)
267269

268-
// Poll for plugin availability
269-
var waited = 0L
270-
while (WearSyncPlugin.instance == null && waited < 15_000L) {
271-
delay(200)
272-
waited += 200
273-
}
274-
275-
// Replay through normal path
276-
WearSyncPlugin.instance?.onWatchMessage(path, data)
277-
stopSelf()
270+
// Service waits until:
271+
// 1) setWatchMessageHandler registered the Channel
272+
// 2) markWatchPipelineReady signalled Rust listeners are bound
273+
// Then queued messages are delivered via channel.send(...)
278274
}
279275
}
280276
```
281277

282-
This pattern — a foreground service that headlessly boots the Tauri runtime — is reusable for any Tauri Android app that needs to process background events. The key insight is that Tauri's runtime initializes quickly (~1 second on modern devices) and the static plugin reference pattern (`companion object { var instance }`) provides a clean way to detect when it's ready.
278+
This pattern — queue first, then foreground-service boot with an explicit readiness handshakeavoids early-replay races during cold start and is reusable for any Tauri Android app that needs reliable background write handling.
283279

284280
## The Watch App: Compose for Wear OS
285281

@@ -362,7 +358,7 @@ The `pathPrefix` filter ensures only messages intended for this app are delivere
362358

363359
**Debounce before syncing.** Without the 500ms batch collector, toggling a few alarms in quick succession would fire multiple Bluetooth round-trips. The debounce window is invisible to the user but dramatically reduces unnecessary Data Layer traffic.
364360

365-
**Foreground services can boot Tauri headlessly.** When you need to process a background event that requires Rust logic, launching the main activity with `FLAG_ACTIVITY_NO_ANIMATION` and polling for plugin readiness is a reliable pattern. The ~1 second boot time is acceptable for background operations.
361+
**Foreground services can boot Tauri headlessly.** For background writes that need Rust logic, queue first, then boot in a foreground service and drain only after explicit pipeline readiness. The ~1 second runtime boot plus queue replay remains acceptable for background operations.
366362

367363
## Conclusion
368364

0 commit comments

Comments
 (0)