refactor(ble): Centralize BLE logic into a core module#4550
Merged
jamesarich merged 25 commits intomainfrom Feb 20, 2026
Merged
refactor(ble): Centralize BLE logic into a core module#4550jamesarich merged 25 commits intomainfrom
jamesarich merged 25 commits intomainfrom
Conversation
This commit refactors the Bluetooth Low Energy (BLE) implementation by moving all related logic from the `app` module into a new, dedicated `:core:ble` module. This improves modularity, reduces code duplication, and simplifies dependencies. Key changes include: - **`core:ble` module:** Introduces a new module to encapsulate all BLE-related functionality, including scanning, connection management, and utility functions. - **`BleConnection` class:** A new class to manage the lifecycle of a single BLE peripheral connection, including state monitoring and service discovery. - **`BleScanner` class:** A wrapper around the Nordic BLE scanner for a consistent scanning API. - **`NordicBleInterface` refactoring:** Updated to use the new `BleConnection` and `BleScanner` classes, simplifying its logic and making it more robust with retry mechanisms. - **Nordic Common Libraries:** Replaces `accompanist-permissions` and custom `BroadcastReceiver` implementations with components from Nordic's `no.nordicsemi.android.common` library for handling permissions (`RequireBluetooth`, `RequireLocation`) and lifecycle-aware receivers. - **Dependency cleanup:** Removes duplicated BLE logic and constants from the `app` and `feature` modules, which now depend on `:core:ble`. - **`kotlin.uuid`:** Migrates from `java.util.UUID` to `kotlin.uuid.Uuid` for multiplatform compatibility. Signed-off-by: James Rich <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
Refactors the app’s Bluetooth Low Energy stack by extracting BLE scanning/connection logic into a new :core:ble module and updating call sites to use Nordic Common libraries for permissions, receivers, and UI components.
Changes:
- Added
:core:blemodule (connection wrapper, scanner wrapper, retry helper, constants, repository/receiver wiring). - Replaced Accompanist permissions + custom receivers with Nordic Common permissions/receiver utilities and scanner UI.
- Migrated many UUID usages from
java.util.UUIDtokotlin.uuid.Uuid.
Reviewed changes
Copilot reviewed 52 out of 52 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| settings.gradle.kts | Includes the new :core:ble module in the build. |
| gradle/libs.versions.toml | Adds Nordic Common deps; adjusts KSP plugin entry. |
| feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/PositionConfigItemList.kt | Switches location permission handling to Nordic Common RequireLocation. |
| feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DeviceConfigItemList.kt | Replaces manual timezone receiver with Nordic Common registerReceiver. |
| feature/settings/build.gradle.kts | Adds Nordic Common core + BLE permissions dependencies. |
| feature/map/src/google/kotlin/org/meshtastic/feature/map/MapViewModel.kt | Migrates random IDs from UUID to Uuid. |
| feature/intro/src/main/kotlin/org/meshtastic/feature/intro/AppIntroductionScreen.kt | Replaces Accompanist permissions with Nordic Common permission composables; adds Bluetooth step. |
| feature/intro/build.gradle.kts | Removes accompanist-permissions; adds Nordic permissions deps; enables Hilt plugin. |
| feature/firmware/src/test/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransportTest.kt | Updates UUID handling in tests to kotlin.uuid.Uuid. |
| feature/firmware/src/test/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransportNordicMockTest.kt | Updates mock OTA GATT setup + UUIDs. |
| feature/firmware/src/test/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransportMtuTest.kt | Updates UUID usage in MTU-related test. |
| feature/firmware/src/test/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransportErrorTest.kt | Updates UUID usage and mock GATT setup for error-path tests. |
| feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransport.kt | Uses new BleConnection/BleScanner; migrates UUIDs; adjusts connect/discovery flow. |
| feature/firmware/build.gradle.kts | Adds dependency on projects.core.ble. |
| core/ui/src/main/kotlin/org/meshtastic/core/ui/component/TimeTickWithLifecycle.kt | Replaces custom BroadcastReceiver management with Nordic Common registerReceiver. |
| core/ui/build.gradle.kts | Adds Nordic Common core dependency. |
| core/prefs/src/main/kotlin/org/meshtastic/core/prefs/analytics/AnalyticsPrefs.kt | Migrates install ID generation to Uuid. |
| core/data/src/test/kotlin/org/meshtastic/core/data/repository/MeshLogRepositoryTest.kt | Migrates test UUIDs to Uuid. |
| core/data/src/google/kotlin/org/meshtastic/core/data/model/CustomTileProviderConfig.kt | Migrates default ID to Uuid. |
| core/common/src/androidMain/kotlin/org/meshtastic/core/common/ContextServices.kt | Adds registerReceiverCompat extension (core-level). |
| core/common/build.gradle.kts | Exposes Nordic Common core from core:common androidMain; adds Kermit to commonMain. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/MeshtasticBleConstants.kt | Centralizes Meshtastic BLE UUID constants using Uuid. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BluetoothState.kt | Moves Bluetooth state model into org.meshtastic.core.ble package. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BluetoothRepository.kt | Moves BLE scan/state logic into core module and uses BleScanner. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BluetoothBroadcastReceiver.kt | Adds core-level Bluetooth broadcast receiver refreshing repository state. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BleScanner.kt | Introduces a wrapper for scanning that yields Peripheral flows. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BleRetry.kt | Introduces generic BLE retry helper with delay/backoff. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BleModule.kt | Adds Hilt module for BLE (CentralManager + singleton scope). |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BleError.kt | Moves BLE error mapping into core module. |
| core/ble/src/main/kotlin/org/meshtastic/core/ble/BleConnection.kt | Adds reusable connection wrapper (state flow + characteristic discovery). |
| core/ble/build.gradle.kts | New Gradle module definition + dependencies for :core:ble. |
| build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt | Globally opts into kotlin.uuid.ExperimentalUuidApi. |
| app/src/test/java/com/geeksville/mesh/repository/radio/NordicBleInterfaceTest.kt | Updates tests to use MeshtasticBleConstants + adjusts retry timing expectation. |
| app/src/test/java/com/geeksville/mesh/repository/radio/NordicBleInterfaceRetryTest.kt | Updates tests to use MeshtasticBleConstants. |
| app/src/test/java/com/geeksville/mesh/repository/radio/NordicBleInterfaceDrainTest.kt | Updates tests to use MeshtasticBleConstants. |
| app/src/main/java/com/geeksville/mesh/ui/connections/components/DeviceListItem.kt | Adds RSSI display via Nordic Common UI RssiIcon. |
| app/src/main/java/com/geeksville/mesh/ui/connections/components/CurrentlyConnectedInfo.kt | Replaces custom BLE signal UI with Nordic RssiIcon. |
| app/src/main/java/com/geeksville/mesh/ui/connections/components/BLEDevices.kt | Replaces custom permissions + lists with Nordic Common ScannerView filter UI. |
| app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsViewModel.kt | Removes dependency on app-level Bluetooth repository. |
| app/src/main/java/com/geeksville/mesh/ui/connections/ConnectionsScreen.kt | Adapts BLE device selection UI flow to new BLEDevices/ScannerView approach. |
| app/src/main/java/com/geeksville/mesh/ui/Main.kt | Switches notification permission request to Nordic Common helper. |
| app/src/main/java/com/geeksville/mesh/service/PacketHandler.kt | Migrates MeshLog UUID creation to Uuid. |
| app/src/main/java/com/geeksville/mesh/service/MeshMessageProcessor.kt | Migrates MeshLog UUID creation to Uuid. |
| app/src/main/java/com/geeksville/mesh/repository/radio/RadioInterfaceService.kt | Uses Nordic simpleSharedFlow; migrates BLE repo/error types to core module. |
| app/src/main/java/com/geeksville/mesh/repository/radio/NordicBleInterfaceSpec.kt | Switches BluetoothRepository import to core module. |
| app/src/main/java/com/geeksville/mesh/repository/radio/NordicBleInterface.kt | Refactors to use BleConnection/BleScanner/centralized constants/retry helper. |
| app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothDevice.kt | Removes app-level Bluetooth bonding helper (moved/removed as part of refactor). |
| app/src/main/java/com/geeksville/mesh/repository/bluetooth/BluetoothBroadcastReceiver.kt | Removes app-level Bluetooth receiver (replaced by core receiver). |
| app/src/main/java/com/geeksville/mesh/model/DeviceListEntry.kt | Uses BLE name pattern constant from core BLE; adds Peripheral.getMeshtasticShortName(). |
| app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt | Switches BluetoothRepository import to core module. |
| app/src/main/java/com/geeksville/mesh/MainActivity.kt | Migrates activity base class to ComponentActivity. |
| app/build.gradle.kts | Adds projects.core.ble + Nordic Common dependencies to app module. |
feature/firmware/src/main/kotlin/org/meshtastic/feature/firmware/ota/BleOtaTransport.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/geeksville/mesh/repository/radio/NordicBleInterface.kt
Show resolved
Hide resolved
This commit introduces a retry mechanism when sending a packet to the radio over BLE. The `retryBleOperation` function is now used to wrap the characteristic write call, improving the reliability of packet transmission. The success log message has also been updated to reflect that the write was successful. Signed-off-by: James Rich <[email protected]>
This commit refactors the BLE connection and error handling logic for better stability and clarity. Key changes include: - A new `connectAndAwait` function in `BleConnection` which attempts to connect and waits for a definitive `Connected` or `Disconnected` state, throwing a specific `BleError` on failure or timeout. - A simplified and more robust `BleError` sealed class to provide clearer error information. - Updated `BleOtaTransport` and `NordicBleInterface` to use `connectAndAwait`, replacing manual timeout and state handling with a more streamlined approach. - Service discovery in `BleConnection` now includes a timeout to prevent indefinite hangs. - Corrected a typo in `libs.versions.toml` for the `coil-svg` dependency. Signed-off-by: James Rich <[email protected]>
This commit refactors the BLE OTA transport test to be more robust and realistic. - Switched from `StandardTestDispatcher` to `UnconfinedTestDispatcher` for more reliable coroutine testing. - Enhanced the mock peripheral to accurately simulate the OTA protocol, including tracking received bytes and sending the final "OK" message correctly after all data chunks are received. - Made the test data size smaller and configurable for faster test execution. - Changed the response channel in `BleOtaTransport` to `UNLIMITED` to prevent potential deadlocks during testing. - Fixed a dependency scope in the `intro` feature module. Signed-off-by: James Rich <[email protected]>
This commit updates the `nordic-ble` library from version `2.0.0-alpha12` to `2.0.0-alpha14`. Key changes include: - Integrating `AndroidEnvironment` to manage Bluetooth state and permissions, replacing the custom `BluetoothBroadcastReceiver`. - Updating BLE module dependencies and providing `AndroidEnvironment` via dependency injection. - Adding the `-Xskip-prerelease-check` Kotlin compiler option to support the alpha library version. Signed-off-by: James Rich <[email protected]>
Adds unit tests for the `BluetoothRepository` to verify its core functionalities. - Introduces tests for the initial state, state updates on Bluetooth power changes, device scanning, and bonded device discovery. - Adds `androidx.lifecycle:lifecycle-runtime-testing` for testing Lifecycle-aware components. - Updates Nordic BLE mock dependency names for consistency (`client-mock` to `client-core-mock`). - Implements the tests using the Nordic BLE mock environment to simulate peripheral devices and Central Manager behavior. Signed-off-by: James Rich <[email protected]>
Decouples the `BleScanner` from the `BluetoothRepository` by introducing it as a constructor dependency. This change improves testability by allowing `BleScanner` to be mocked in `BluetoothRepositoryTest`. The tests have been refactored to use mocks for `BleScanner`, enabling more focused and reliable testing of the repository's logic without relying on the specifics of the BLE scanning implementation. The `BleScanner` class is also updated with an `@Inject` annotation to support dependency injection. Signed-off-by: James Rich <[email protected]>
The test `drainPacketQueueAndDispatch` was previously ignored due to intermittent failures related to timing in the Nordic BLE mock library. This commit re-enables the test by removing the `@Ignore` annotation. Signed-off-by: James Rich <[email protected]>
Signed-off-by: James Rich <[email protected]>
This commit introduces several modern Android development practices to improve the `MainActivity` and related components: - **Enable Predictive Back Gesture**: Enables the new predictive back gesture introduced in Android 13 by setting `enableOnBackInvokedCallback="true"` in the `AndroidManifest.xml`. - **Modernize Intent Handling**: Replaces the deprecated `onNewIntent` override with `addOnNewIntentListener`. Uses `IntentCompat` for type-safe handling of `Parcelable` extras from NFC intents. - **Improve Edge-to-Edge Display**: Updates `enableEdgeToEdge` to provide theme-aware (dark/light) system bar styling for a more seamless UI. - **Optimize Startup**: Implements `ReportDrawnWhen` to signal to the system when the UI is fully drawn, improving startup performance measurement. - **Clean Up Splash Screen**: Simplifies the splash screen theme (`styles.xml`) and removes the obsolete `colors.xml` file by referencing `android:color/black` directly in the splash icon drawable. - **Use Lifecycle-Aware Coroutines**: Migrates from `collectAsState` to `collectAsStateWithLifecycle` for more efficient and safer UI state collection. - **Fix Bitwise Operation**: Corrects a logical error in `MeshServiceClient` by using the bitwise `or` operator instead of `+` for combining service binding flags. Signed-off-by: James Rich <[email protected]>
Closes the MeshServiceClient connection when the app enters the stopped state. This is done by implementing the `onStop` lifecycle callback to call `close()`. Signed-off-by: James Rich <[email protected]>
…libs # Conflicts: # app/src/main/java/com/geeksville/mesh/MainActivity.kt # app/src/main/java/com/geeksville/mesh/repository/radio/NordicBleInterface.kt # app/src/main/java/com/geeksville/mesh/service/MeshMessageProcessor.kt # app/src/main/java/com/geeksville/mesh/service/PacketHandler.kt # build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt # core/ui/src/main/kotlin/org/meshtastic/core/ui/component/TimeTickWithLifecycle.kt # feature/settings/src/main/kotlin/org/meshtastic/feature/settings/radio/component/DeviceConfigItemList.kt # gradle/libs.versions.toml
# Conflicts: # app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt
This commit introduces significant improvements to the stability of Bluetooth Low Energy (BLE) connections and refactors the testing infrastructure. A race condition in the Firmware Over-the-Air (OTA) update process has been resolved. Previously, a very fast device could send a response before the client was ready to listen, causing the update to fail. By waiting for the notification subscription to be fully established before proceeding, this issue is now fixed. Similarly, the main radio connection logic has been hardened. The connection process now explicitly waits for all required characteristic notifications to be successfully subscribed before considering the connection complete. This prevents race conditions and ensures the link is fully operational. The testing framework has been updated to use the more advanced `MockAndroidEnvironment` from the Nordic BLE library. This provides a more realistic and robust simulation of the BLE stack, improving the reliability of our tests. Finally, a deprecated `ZoneIdExtensions.kt` file has been removed, and the dependencies for the Nordic BLE library have been updated. **BREAKING CHANGE:** The `nordic-log` dependency has been removed. All tests now use the `MockAndroidEnvironment` for BLE simulation. This might require adjustments in downstream modules or test configurations that relied on the previous setup. Signed-off-by: James Rich <[email protected]>
This commit introduces several UI enhancements to the Connections screen for a more polished and consistent user experience. It also adds foundational UI tests for this screen. Key changes include: - **Consistent Sizing and Spacing:** The layout of the `ConnectingDeviceInfo` and `DeviceListItem` components has been refined with standardized spacing, padding, and typography to align with the Material Design style. Progress indicators and icons have also been resized for better visual balance. - **Improved BLE Device Display:** BLE devices in the list are now wrapped in `Card` elements for better visual separation. - **Throttled RSSI Updates:** The RSSI value displayed for BLE devices is now updated at a throttled rate to reduce visual noise and align with the device's polling frequency. - **Scrollable Device Lists:** The device lists for TCP and USB connections are now independently scrollable, preventing the entire screen from scrolling and keeping the connection type tabs visible. - **Refactored NetworkDevices Composable:** The logic for displaying network devices has been extracted into an internal, previewable composable function (`NetworkDevicesInternal`), improving testability and code organization. - **UI Test Infrastructure:** Added new instrumentation tests for the `ConnectionsScreen` using `MockAndroidEnvironment` to simulate different Bluetooth states (enabled/disabled) and verify the UI's response. Corresponding test dependencies have been added to the build configuration. Signed-off-by: James Rich <[email protected]>
This commit enhances the device connection screen by displaying associated node information (long name and short name) for each discovered or saved device. When a device is found via BLE, USB, or TCP, the app now attempts to find a matching node from the current node database. If a match is found, the node's chip, showing its long and short name, is displayed next to the device name in the list. This provides users with more context about the devices they are connecting to. The matching logic is specific to the connection type: - **BLE:** Matches using the device's short name from its advertisement data. - **TCP (mDNS):** Matches using the node ID from the mDNS TXT record. - **USB & Recent TCP:** Attempts to match using the last part of the device name (e.g., the `_xxxx` suffix). To support this, the `DeviceListEntry` data structure has been updated to include an optional `Node` property. Signed-off-by: James Rich <[email protected]>
This commit refactors the device connection screen for a cleaner and more consistent user experience, and improves how Bluetooth devices are named. The "Available Bluetooth Devices" and "Recent Network Devices" lists have been updated to use a consistent card-based layout with a shared headline style. The previous `TitledCard` has been replaced with a standard `Card` and `Text` combination for better visual alignment with the rest of the UI. In the string resources, "BLE Devices" has been renamed to "Available Bluetooth Devices" for clarity. Additionally, a new "Friendly address" string has been introduced. Signed-off-by: James Rich <[email protected]>
This commit refactors the connection management logic by separating the concerns of BLE device scanning from the broader connection and device management. A new `ScannerViewModel` has been created to handle the presentation logic for all connection types (BLE, USB, TCP), replacing the monolithic `BTScanModel`. The responsibility for initiating and managing BLE scans has been moved from the `BluetoothRepository` to the `ScannerView` composable, leveraging the Nordic `ScannerView` component for a more standard and encapsulated implementation. This change simplifies the `BluetoothRepository` by removing scanning-related flows and logic, allowing it to focus solely on managing Bluetooth state and bonding. Key changes: - `BTScanModel` has been deleted and replaced by `ScannerViewModel`. - `BluetoothRepository` no longer handles BLE scanning; this is now managed by the `ScannerView`. - The `ConnectionsScreen` and related composables have been updated to use `ScannerViewModel`. - Unused flows and properties in `UsbRepository` and `UIViewModel` have been removed. BREAKING CHANGE: The `BTScanModel` class has been removed and its responsibilities have been refactored into `ScannerViewModel` and the `ScannerView` UI component. The `BluetoothRepository` API has changed, as it no longer provides BLE scanning functionality. Downstream dependencies on `BTScanModel` or the scanning methods in `BluetoothRepository` will need to be updated. Signed-off-by: James Rich <[email protected]>
This commit centralizes common utility classes and functions from the `app` module into a new `core/common` module. This consolidation removes duplicated code, improves modularity, and simplifies dependencies across the feature modules.
Key changes include:
- **Creation of `core/common` module**: A new module to house shared, platform-agnostic and platform-specific utilities.
- **Moved utility classes**:
- `BuildUtils`, `DebugLogFile`, `BinaryLogFile`, `DateUtils` and `Utf8ByteLengthFilter` moved to `core/common`.
- Concurrency helpers like `ServiceClient`, `SequentialJob`, `SyncContinuation`, `DeferredExecution`, and `handledLaunch` are now in `core/common`.
- Exception handling utilities (`Exceptions`, `exceptionReporter`, `toRemoteExceptions`) have been centralized.
- **Relocated extension functions**:
- `Modifier.thenIf` moved to `core/ui`.
- Time-related extensions (`nowMillis`, `nowSeconds`, etc.) are now in `core/common`.
- `getInitials` logic moved into `core/model`.
- **Dependency updates**: `build.gradle.kts` files across various modules (`core/data`, `core/service`, `core/ui`, `feature/node`, etc.) have been updated to depend on the new `core/common` module.
- **Code cleanup**:
- Removed `ExperimentalMaterial3ExpressiveApi` annotation as it is no longer needed. Replaced `CircularWavyProgressIndicator` with `CircularProgressIndicator`.
- Renamed `UIState.kt` to `UIViewModel.kt` for clarity.
- Simplified Paging 3 related code in `ContactsScreen` for better readability.
This refactoring reduces code duplication and establishes a clearer architectural pattern for shared utilities, making the codebase more maintainable and scalable.
Signed-off-by: James Rich <[email protected]>
This commit introduces `ServiceClient`, a new class designed to manage the lifecycle of a bound Android service connection in a more robust and testable way. The `ServiceClient` handles the complexities of binding to a service, including: - Retrying the bind operation on initial failure. - Throwing a `BindFailedException` after multiple failed attempts. - Providing a `waitConnect()` method that blocks until the service is successfully connected, which is useful for ensuring the service is ready before use. - Managing unbinding when `close()` is called. Comprehensive unit tests (`ServiceClientTest`) have been added to validate this new functionality, covering successful connections, retry logic, connection waiting, and the unbinding process. Additionally, a minor refactoring was done in `MigrationTest.kt` to update an import path for `nowMillis`, moving it to the `core.common` package. Signed-off-by: James Rich <[email protected]>
This commit introduces comprehensive documentation for the project's architecture and the modernized Bluetooth Low Energy (BLE) stack. The main `README.md` has been updated to include a high-level overview of the app's architecture, covering UI, state management, dependency injection, navigation, and the data layer. It also now points to the new BLE documentation. A detailed `README.md` has been added to the `core/ble` module. This new file explains the move to Nordic Semiconductor's Coroutine-based BLE libraries, replacing the legacy implementation. It outlines the key components of the new stack, including `NordicBleInterface`, `BluetoothRepository`, and `BleConnection`, and provides guidance on architecture and testing within the module. Finally, the `AGENTS.md` file, which serves as a guide for contributors, has been updated to reflect these architectural changes. It now includes a dedicated section for the new BLE stack, directing developers to use the modern abstractions and avoid legacy APIs. Signed-off-by: James Rich <[email protected]>
This commit populates the `README.md` file for each module with a detailed overview, a description of its key components, and an auto-generated Mermaid dependency graph. This documentation provides a high-level understanding of each module's role within the application architecture. Additionally, the `build-logic` for graph generation has been improved to correctly identify Android Feature modules and ensure the README files are updated only when the graph content changes. The `CONTRIBUTING.md` has also been updated to reflect the new, centralized string resource management in the `:core:strings` module. Signed-off-by: James Rich <[email protected]>
This commit refactors the project's testing infrastructure to improve consistency and maintainability. Key changes include: - A legacy UI test, `ConnectionScreenTest.kt`, has been removed as its functionality is now covered by more modern tests utilizing `MockAndroidEnvironment`. - The `getInitials` utility function has been moved from the `app` module to `core.model.util` to be accessible across the project. - Time-related utility functions like `nowMillis`, `nowSeconds`, etc., have been relocated from `core.model.util` to a new `core.common.util` module. - The project's Android Gradle Plugin has been updated, enabling `isIncludeAndroidResources = true` for unit tests, which allows them to access Android resources. - String resource fetching in tests has been standardized to use `org.meshtastic.core.strings.getString`. - A dummy Maps API key has been added to the "google" product flavor's manifest placeholders to prevent build failures in environments without a `secrets.properties` file. - The SDK version for `MeshServiceBroadcastsTest` has been explicitly set to 34. **BREAKING CHANGE:** The `getInitials()` and various time utility functions (`nowMillis`, `toInstant`, etc.) have moved. Downstream modules and tests must update their imports to use the new locations in `org.meshtastic.core.model.util.getInitials` and `org.meshtastic.core.common.util` respectively. Signed-off-by: James Rich <[email protected]>
This commit updates the internal (`AGENTS.md`) and external (`CONTRIBUTING.md`) documentation to reflect current testing best practices. The guidelines now recommend using Robolectric for JVM-based Compose UI tests, which are faster than instrumented tests. A best practice note has been added to pass mocked ViewModels directly to Composables in these tests instead of using Hilt. Additionally, a critical workaround for developers using Java 17 is included: annotate Robolectric tests with `@Config(sdk = [34])` to prevent compatibility issues with Android SDK 35. The documentation also clarifies the distinction between component-level JVM tests and full end-to-end instrumented tests. Signed-off-by: James Rich <[email protected]>
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: Migrate BLE stack to Nordic Android Common Libraries
Overview
This PR migrates the entire Bluetooth Low Energy (BLE) stack to use Nordic Semiconductor's Android Common Libraries and Kotlin BLE Library. This modernization replaces the legacy Bluetooth implementation with a more robust, Coroutine-based architecture provided by the Nordic libraries, known for their reliability in the Android BLE ecosystem.
Key Changes
1. Dependencies
no.nordicsemi.kotlin.ble:*(Kotlin BLE Library) for modern, Coroutine-based BLE communication.no.nordicsemi.android.common:*(Common Libraries) for standardized UI components, scanning, and permission handling.2. Core BLE Architecture (
core/ble,app/src/.../radio)NordicBleInterfaceas the newIRadioInterfaceimplementation for BLE, replacing the legacyBluetoothInterface. It usesBleConnectionto manage connections via Nordic'sCentralManager.BluetoothRepositoryhas been rewritten to use Nordic'sCentralManagerfor device scanning, state management, and bonding.BleConnectionandBleRetryutilities to handle connection lifecycles, service discovery, and retry logic more robustly.3. Firmware OTA (
feature/firmware)BleOtaTransport) to leverage the Nordic Kotlin BLE library. This improves the reliability of firmware updates over BLE, including better handling of MTU negotiation and characteristic notifications.4. UI & Scanning (
app/src/.../ui/connections)BLEDevicescomposable now utilizes the Nordic Scanner View (no.nordicsemi.android.common.scanner.view.ScannerView). This provides a standardized, feature-rich scanning interface with built-in filtering and permission handling.ScannerViewModelandDeviceListEntryhave been updated to wrap Nordic'sPeripheralobjects, ensuring consistent device representation across the app.5. Integration
RadioInterfaceServiceandInterfaceFactory(viaRadioRepositoryModule) to bindInterfaceId.BLUETOOTHto the newNordicBleInterfaceSpec.Benefits
Verification