Files
Meshtastic-Android/docs/kmp-status.md

9.9 KiB

KMP Migration Status

Last updated: 2026-03-13

Single source of truth for Kotlin Multiplatform migration progress. For the forward-looking roadmap, see roadmap.md. For completed decision records, see decisions/.

Summary

Meshtastic-Android has completed its Android-first structural KMP migration across core logic and feature modules, with full JVM cross-compilation validated in CI. The desktop target has a working Navigation 3 shell, TCP transport with full mesh handshake, and multiple features wired with real screens.

Modules that share JVM-specific code between Android and desktop now standardize on the meshtastic.kmp.jvm.android convention plugin, which creates jvmAndroidMain via Kotlin's hierarchy template API instead of manual dependsOn(...) source-set wiring.

Module Inventory

Core Modules (20 total)

Module KMP? JVM target? Notes
core:proto Protobuf definitions
core:common Utilities, jvmAndroidMain source set
core:model Domain models, jvmAndroidMain source set
core:repository Domain interfaces
core:di Dispatchers, qualifiers
core:navigation Shared Navigation 3 routes
core:resources Compose Multiplatform resources
core:datastore Multiplatform DataStore
core:database Room KMP
core:domain UseCases
core:prefs Preferences layer
core:network Ktor, StreamFrameCodec, TcpTransport
core:data Data orchestration
core:ble BLE abstractions in commonMain; Nordic in androidMain
core:nfc NFC contract in commonMain; hardware in androidMain
core:service Service layer; Android bindings in androidMain
core:ui Shared Compose UI, jvmAndroidMain + jvmMain actuals
core:testing Shared test doubles, fakes, and utilities for commonTest
core:api Android-only (AIDL). Intentional.
core:barcode Android-only (CameraX). Flavor split minimised to decoder factory only (ML Kit / ZXing). Shared contract in core:ui.

18/20 core modules are KMP with JVM targets. The 2 Android-only modules are intentionally platform-specific, with shared contracts already abstracted into core:ui/commonMain.

Feature Modules (7 total — all KMP with JVM)

Module UI in commonMain? Desktop wired?
feature:settings ~35 real screens; shared ChannelViewModel
feature:node Adaptive list-detail; shared NodeContextMenu
feature:messaging Adaptive contacts + messages; 17 shared files in commonMain (ViewModels, MessageBubble, MessageItem, QuickChat, Reactions, DeliveryInfo, actions, events)
feature:connections Shared ConnectionsScreen with dynamic transport detection
feature:intro
feature:map Placeholder; shared NodeMapViewModel
feature:firmware Placeholder; DFU is Android-only

Desktop Module

Working Compose Desktop application with:

  • Navigation 3 shell (NavigationRail + NavDisplay) using shared routes
  • Full Koin DI graph (stubs + real implementations)
  • TCP transport with auto-reconnect and full want_config handshake
  • Adaptive list-detail screens for nodes and contacts
  • Dynamic Connections screen with automatic discovery of platform-supported transports (TCP)
  • Desktop language picker backed by UiPreferencesDataSource.locale, with immediate Compose Multiplatform resource updates
  • Navigation-preserving locale switching via Main.kt staticCompositionLocalOf recomposition instead of recreating the Nav3 backstack
  • Node detail metrics screens (Device, Environment, Signal, Power, Pax) wired with shared KMP + Vico charts
  • 7 desktop-specific screens (Settings, Device, Position, Network, Security, ExternalNotification, Debug)
  • Native release pipeline generating .dmg (macOS), .msi (Windows), and .deb (Linux) installers in CI

Scorecard

Area Score Notes
Shared business/data logic 9/10 All core layers shared; RadioTransport interface unified
Shared feature/UI logic 8.5/10 All 7 KMP; feature:connections unified with dynamic transport detection
Android decoupling 8/10 No known java.* calls in commonMain; app module extraction in progress
Multi-target readiness 8/10 Full JVM; release-ready desktop; iOS not declared
CI confidence 9/10 25 modules validated (including feature:connections); native release installers automated
DI portability 8/10 Koin annotations in commonMain; supportedDeviceTypes injected per platform
Test maturity 8/10 131 commonTest + 89 platform-specific = 219 tests across all 7 features; core:testing established

See decisions/architecture-review-2026-03.md for the full gap analysis.

Completion Estimates

Lens %
Android-first structural KMP ~98%
Shared business logic ~95%
Shared feature/UI ~90%
True multi-target readiness ~75%
"Add iOS without surprises" ~65%

Proposed Next Steps for KMP Migration

Based on the latest codebase investigation, the following steps are proposed to complete the multi-target and iOS-readiness migrations:

  1. Extract remaining App-Only ViewModels: Migrate the 5 remaining Android*ViewModels by isolating their Android-specific dependencies (e.g., android.net.Uri for file I/O, Location permissions) behind expect/actual or injected interface abstractions.
  2. Wire Desktop Features: Complete desktop UI wiring for feature:intro and implement a shared fallback for feature:map (which is currently a placeholder on desktop).
  3. Decouple Firmware DFU: feature:firmware relies on Android-only DFU libraries. Evaluate wrapping this in a shared KMP interface or extracting it into a separate plugin to allow the core feature:firmware module to be fully utilized on desktop/iOS.
  4. Prepare for iOS Target: Set up an initial skeleton Xcode project to start validating commonMain compilation on Kotlin/Native (iOS).

Key Architecture Decisions

Decision Status Details
Navigation 3 parity model (shared TopLevelDestination + platform adapters) Done Both shells use shared enum + parity tests. See decisions/navigation3-parity-2026-03.md
Hilt → Koin Done See decisions/koin-migration.md
BLE abstraction (Nordic Hybrid) Done See decisions/ble-strategy.md
Material 3 Adaptive (JetBrains) Done Version 1.3.0-alpha06 aligned with CMP 1.11.0-alpha04
JetBrains lifecycle/nav3 alias alignment Done All forked deps use jetbrains-* prefix in version catalog; core:data commonMain uses JetBrains lifecycle runtime
Expect/actual consolidation Done 7 pairs eliminated; 15+ genuinely platform-specific retained
Transport deduplication Done StreamFrameCodec + TcpTransport shared in core:network
Transport UI Unification Done RadioInterfaceService provides dynamic transport capability to shared UI
Emoji picker unification Done Single commonMain implementation replacing 3 platform variants

Navigation Parity Note

  • Desktop and Android both use the shared TopLevelDestination enum from core:navigation/commonMain — no separate DesktopDestination remains.
  • Both shells iterate TopLevelDestination.entries with shared icon mapping from core:ui (TopLevelDestinationExt.icon).
  • Desktop locale changes now trigger a full subtree recomposition from Main.kt without resetting the shared Navigation 3 backstack, so translated labels update in place.
  • Firmware remains available as an in-flow route instead of a top-level destination, matching Android information architecture.
  • Parity tests exist in core:navigation/commonTest (NavigationParityTest) and desktop/test (DesktopTopLevelDestinationParityTest).
  • Remaining parity work is documented in decisions/navigation3-parity-2026-03.md: serializer registration validation and platform exception tracking.

Remaining App-Only ViewModels

Only ViewModels with genuine Android-specific logic retain wrappers:

ViewModel Android-Specific Reason
AndroidSettingsViewModel File I/O via android.net.Uri
AndroidRadioConfigViewModel Location permissions, file I/O
AndroidDebugViewModel Locale-aware hex formatting
AndroidMetricsViewModel CSV export via android.net.Uri
UIViewModel Deep links via android.net.Uri, IMeshService

Extracted to shared commonMain (no longer app-only):

  • ChannelViewModelfeature:settings/commonMain
  • NodeMapViewModelfeature:map/commonMain

Prerelease Dependencies

Dependency Version Why
Compose Multiplatform 1.11.0-alpha04 Required for JetBrains Adaptive 1.3.0-alpha06
Koin 4.2.0-RC2 Nav3 + K2 compiler plugin support
JetBrains Lifecycle 2.10.0-beta01 Multiplatform ViewModel/lifecycle
JetBrains Navigation 3 1.1.0-alpha04 Multiplatform navigation
Nordic BLE 2.0.0-alpha16 Behind abstraction boundary

Policy: Stable by default. RC when it unlocks KMP functionality. Alpha only behind hard abstraction seams. Do not downgrade CMP or Koin — they enable critical KMP features.

References