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:
- a separate Android module (e.g.
android/wear/) with its own Flutter engine embedding, or - a
wearproduct flavor of the existingandroid/appmodule, sharing all Dart code and plugins, with a dedicatedlib/main_wear.dartentrypoint.
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) toandroid/app/build.gradle.kts, a manifest overlay underandroid/app/src/wear/, andlib/main_wear.dart. - the wear manifest overlay must declare
android.hardware.type.watchandcom.google.android.wearable.standalone. - the wear flavor keeps the existing desugaring config; nothing extra is
required for
flutter_local_notifications. wear_plusis added topubspec.yamlin 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).