NexaFlow v3.76.0
Added
-
Wear OS companion app — a new
:wearmodule delivers a native Wear OS 3
watch companion that surfaces NexaFlow automations directly on the user's
wrist, enabling monitoring and execution without reaching for the phone.- Automation list screen (
AutomationListScreen): circular-display-optimised
ScalingLazyColumnpresenting every automation with its enable/disable state,
last-run outcome badge, and a dedicated "Run Now" button per card. While a
run command is in-flight the button is replaced by aCircularProgressIndicator
so the user always knows the watch is acting. - Automation detail screen (
AutomationDetailScreen): swipe-to-dismiss
detail view showing the full automation name, a timestamped last-run result
chip (success ✓ / failure ✗ with message excerpt), an enable/disable
ToggleButton, and a prominent "Run Now" button. - Navigation:
SwipeDismissableNavHostprovides the standard Wear OS
swipe-back gesture between the list and detail destinations. - Sealed UI state model (
WearUiState): four states —Connecting
(awaiting first sync),Empty(phone has no automations),Loaded(normal
view), andRunning(a manual run is in-flight) — drive the UI without
intermediate booleans or nullable fields. - Real-time data sync via the Wearable Data Layer:
WearSyncRepository
holds aStateFlow<List<WearAutomationDto>>that is updated by the
backgroundWearDataListenerServiceon everyDATA_CHANGEDevent without
polling or explicit refresh. - Watch → Phone command channel:
WearDataLayerClientdiscovers the
nearest connected phone node viaNodeClientand sends typed
MessageClientmessages. Run commands are encoded as the automation ID;
toggle commands encode"automationId:true/false"over a
WearableListenerServicebridge. - Hilt dependency injection in the watch app:
WearModuleprovides
singletonMessageClientandNodeClientinstances;WearViewModelis a
standard@HiltViewModel;WearDataListenerServiceuses
@AndroidEntryPoint. - String resources localised in all 11 supported locales:
en ar de es fr hi ja pt ru tr zh-rCN. - Companion APK bundled via
wearApp(project(":wear"))in:appso a
single Play Store install delivers both the phone and watch APKs.
- Automation list screen (
-
Phone-side Wear OS bridge (in
:app):WearSyncManager: subscribes toAutomationRepositoryand
HistoryRepositoryvia acombineflow, debounces rapid saves by 500 ms
to coalesce bulk operations, serialises the result toWearAutomationDto
JSON, and pushes it as an urgent DataItem to all connected watches. A
monotonicupdatedAttimestamp forces aDATA_CHANGEDdelivery even when
the automation list is unchanged, guaranteeing state convergence after a
watch reconnect.WearCommandListenerService: aWearableListenerServicedeclared in the
phone manifest with aMESSAGE_RECEIVEDfilter scoped to/nexaflow/
paths. UsesEntryPointAccessors(instead of@AndroidEntryPoint) for safe
Hilt injection in a platform-managed service. Routes run commands to
ExecutionEngine.forceRun()and toggle commands to
AutomationRepository.updateAutomationStatus()followed by
ExecutionEngine.notifyAutomationsChanged()so stateful monitors react
immediately.WearSyncManageris started inNexaFlowApplication.onCreate()inside the
existing best-effort startup block; failures are caught and logged without
impacting any other startup component.
-
Shared Wear OS protocol constants added to
AutomationIntents.kt
(WEAR_PATH_AUTOMATIONS,WEAR_PATH_RUN_COMMAND,WEAR_PATH_TOGGLE_COMMAND,
WEAR_KEY_PAYLOAD,WEAR_KEY_UPDATED_AT,WEAR_TOGGLE_SEPARATOR) as the
single authoritative source for the Data Layer communication contract on the
phone side, mirrored byWearProtocolin the watch module. -
New Gradle dependencies (
libs.versions.toml):com.google.android.gms:play-services-wearable:19.0.0— Data Layer API
(both modules).androidx.wear.compose:compose-material3:1.5.0-alpha26— Wear OS
Material 3 component library.androidx.wear.compose:compose-foundation:1.5.0-alpha26—ScalingLazyColumn
and watch-optimised layout primitives.androidx.wear.compose:compose-navigation:1.5.0-alpha26—
SwipeDismissableNavHost.org.mockito.kotlin:mockito-kotlin:5.4.0(test) — mock support for
WearDataLayerClientin unit tests.app.cash.turbine:turbine:1.2.0(test) —StateFlowassertion helpers.
Tests
WearAutomationDtoSerializationTest(7 cases): round-trip JSON
serialisation, null optional fields,ignoreUnknownKeysforward
compatibility, malformed JSON graceful degradation, empty-array handling,
state replacement on successive calls, and multi-DTO parsing.WearViewModelTest(5 cases): initialConnectingstate,Loaded
transition after first sync,Emptystate on empty push,runNow
command delegation verification,toggleEnabledcommand delegation
verification. UsesStandardTestDispatcherfor deterministic coroutine
control.WearSyncManagerDtoTest(4 cases): phone-side DTO round-trip
serialisation, nullable-field encoding, empty-list serialisation, and
lastRunMessagetruncation boundary.WearCommandProtocolTest(8 cases): toggle payload encoding fortrueand
false, separator parsing, invalid-boolean rejection, missing-separator
detection, and protocol path constant verification.
Validation
- Zero string parity problems across all 11 locales verified via
check_strings_parity.py(covers both:appand:wearresource trees). - Zero hardcoded non-English strings in shipped Kotlin sources verified via
check_hardcoded_text.py(425 sources clean). - Builder catalog parity verified clean (
CATALOG_PARITY: OK — 56 triggers, 176 actions) viaaudit_catalog_and_releases.py catalog. No new trigger or
action enum values were added in this release. - All 11 locale
values-*/strings.xmlfiles created for the:wearmodule
with exact key parity againstvalues/strings.xml.
Quality evidence
The tag workflow gates publication on the following automated checks. Consult the exact tag run and validation record for results; these checks do not establish physical-device coverage:
- Android Lint (zero-tolerance: UnusedResources, MissingTranslation, ExtraTranslation,
UnusedIds, CheckResult, HardcodedText, TypographyDashes) and Detekt static analysis. - Catalog parity gates: every
TriggerTypeandActionTypeenum value must exist
exactly once in the builder picker (restricted entries are pinned explicitly). - Full unit-test suite, including Room migration, scheduler, lifecycle, and recovery
regression coverage. - Release build with R8 full shrinking, APK signature verification (v2/v3 schemes and
certificate-fingerprint match against the production keystore), 16 KB page-size
alignment check, zipalign verification, bundletool AAB validation, and Gradle
dependency verification (SHA-256 checksums for every artifact). - Tag hygiene: the tag must match the newest
CHANGELOG.mdentry, so the notes below
are the actual, reviewed change record for this release.
Install
- Download
NexaFlow-<version>.apkfrom the assets below and install it. - Android updates require a compatible version code and the same signing certificate.
Back up important tasks before upgrading. - Pre-release tags (
alpha/beta/rc) are marked as pre-releases automatically.