Skip to content

6. ship the Wear OS app as a product flavor of the Android module

status

accepted (stage 10.0 audit complete)

context

phase 10 brings the app to Wear OS. A Wear OS app is a regular Android app with extra manifest metadata (android.hardware.type.watch, com.google.android.wearable.standalone), so there are two ways to ship it:

  1. a separate Android module (e.g. android/wear/) with its own Flutter engine embedding, or
  2. a wear product flavor of the existing android/app module, sharing all Dart code and plugins, with a dedicated lib/main_wear.dart entrypoint.

a stage 10.0 research spike audited the app's core plugins on Wear OS using a scratch project (wear_plugin_audit, kept outside this repo) built with the same plugin versions as this app.

decision

build the watch app as a wear product flavor of android/app with a dedicated lib/main_wear.dart entrypoint (stage 10.1). a separate module would duplicate gradle config, signing, plugin registration, and CI for no benefit, since the flavor already gives us a distinct application id (.wear suffix), its own manifest overlay, and independent Play listings.

use the wear_plus package (v1.2.5) for watch shape, ambient mode callbacks, and wear-specific widgets. it is actively maintained (its predecessor wear is not), requires only minSdk 23, and builds cleanly against Flutter 3.44 / Dart 3.12.

plugin support matrix

audited with a scratch project on Flutter 3.44.2 targeting a Wear OS debug apk. "build" is whether the plugin compiles into a wear apk; "runtime" is behavior on a physical watch.

plugin version build runtime on watch notes
flutter_soloud 4.1.7 ok pass engine initializes; one-shot bell and looping background play; concurrent playback works; bg loop stop stops cleanly
drift / sqlite3 2.34.3 / 3.5.1 ok pass sqlite3 3.x native hooks bundle the library; no sqlite3_flutter_libs needed; inserts persist across app restarts (row count grew 2 → 6)
flutter_local_notifications 22.3.0 ok (needs core library desugaring) pass permission granted, immediate notification shown; delayed (~1 min) notification scheduled; core library desugaring is required for the build
flutter_tts 4.2.5 ok pass 371 voices reported; speak() works (audio audible on the watch)
wear_plus 1.2.5 ok pass (partial ambient/rotary exercise) WatchShape returns correct layout; AmbientMode reports WearMode.active; rotary scroll and ambient transitions were not explicitly exercised in this run

runtime results were collected on a physical Wear OS watch (serial 192.168.0.27:38067 via Wi-Fi adb) from the wear_plugin_audit scratch app; adb logcat -s flutter captured all test outcomes.

consequences

  • stage 10.1 adds flavorDimensions (phone, wear) to android/app/build.gradle.kts, a manifest overlay under android/app/src/wear/, and lib/main_wear.dart.
  • the wear manifest overlay must declare android.hardware.type.watch and com.google.android.wearable.standalone.
  • the wear flavor keeps the existing desugaring config; nothing extra is required for flutter_local_notifications.
  • wear_plus is added to pubspec.yaml in stage 10.2 (watch ui shell); it is harmless on non-watch platforms since it is only referenced from wear-only widgets.
  • any plugin that fails its runtime check on the watch gets a kotlin platform-channel shim task added to the owning stage (10.3 audio/tts, 10.4 Data Layer, 10.8 notifications).