Migrated to new connection state

This commit is contained in:
hiar
2025-08-13 16:17:35 +02:00
committed by Himali Aryal
parent b6ec8c7e64
commit 8a7eb67d72
4 changed files with 37 additions and 50 deletions

View File

@@ -135,7 +135,7 @@ internal class ProfileService : NotificationService() {
}
}
override fun getConnectionState(address: String): StateFlow<ConnectionState>? {
override fun connectionState(address: String): StateFlow<ConnectionState>? {
val peripheral = getPeripheralById(address) ?: return null
return peripheral.state.also { stateFlow ->
connectionJobs[address]?.cancel()
@@ -149,14 +149,16 @@ internal class ProfileService : NotificationService() {
}
}
ConnectionState.Connecting -> _disconnectionReason.tryEmit(null)
is ConnectionState.Disconnected -> {
_disconnectionReason.tryEmit(StateReason(state.reason))
ConnectionState.Connecting, ConnectionState.Disconnecting -> {
// No action needed, just observing the state
}
ConnectionState.Closed -> return@onEach
ConnectionState.Disconnecting -> {
is ConnectionState.Disconnected -> {
if (state.reason == null) {
_disconnectionReason.tryEmit(null)
return@onEach
} else
_disconnectionReason.tryEmit(StateReason(state.reason!!))
connectionJobs[address]?.cancel()
handleDisconnection(address)
}
@@ -185,7 +187,6 @@ internal class ProfileService : NotificationService() {
centralManager.connect(peripheral, options = ConnectionOptions.Direct())
} catch (e: Exception) {
Timber.e(e, "Failed to connect to the ${peripheral.address}")
stopForegroundService() // Stop service if connection fails
}
}
@@ -221,7 +222,6 @@ internal class ProfileService : NotificationService() {
)
} catch (e: Exception) {
Timber.tag("ObserveServices").e(e)
handleDisconnection(peripheral.address)
}
}
}
@@ -261,13 +261,13 @@ internal class ProfileService : NotificationService() {
/**
* Handle disconnection and cleanup for the given peripheral.
*/
private fun handleDisconnection(peripheral: String) {
private fun handleDisconnection(device: String) {
val currentDevices = _connectedDevices.value.toMutableMap()
currentDevices[peripheral]?.let {
currentDevices.remove(peripheral)
currentDevices[device]?.let {
currentDevices.remove(device)
_connectedDevices.tryEmit(currentDevices)
}
clearJobs(peripheral)
clearJobs(device)
clearFlags()
stopServiceIfNoDevices()
}

View File

@@ -5,7 +5,7 @@ import no.nordicsemi.kotlin.ble.core.ConnectionState.Disconnected.Reason
fun toReason(reason: Reason): String =
when (reason) {
Reason.Cancelled -> "Connection was cancelled."
Reason.LinkLoss -> "Device signal has been lost."
Reason.LinkLoss -> "The device got out of range or has turned off."
Reason.Success -> "Device disconnected successfully."
Reason.TerminateLocalHost -> "Device disconnected by the local host."
Reason.TerminatePeerUser -> "Device disconnected by the peer user."
@@ -13,4 +13,5 @@ fun toReason(reason: Reason): String =
is Reason.Unknown -> "Oops...! Connection went on a coffee break."
Reason.UnsupportedAddress -> "Device disconnected due to unsupported address."
Reason.InsufficientAuthentication -> "Device disconnected due to insufficient authentication."
Reason.UnsupportedConfiguration -> "Connection attempt was aborted due PHY negotiations failure."
}

View File

@@ -9,7 +9,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
@@ -23,14 +22,12 @@ import no.nordicsemi.android.common.navigation.Navigator
import no.nordicsemi.android.common.navigation.viewmodel.SimpleNavigationViewModel
import no.nordicsemi.android.log.LogSession
import no.nordicsemi.android.log.timber.nRFLoggerTree
import no.nordicsemi.android.service.profile.CustomReason
import no.nordicsemi.android.service.profile.ProfileServiceManager
import no.nordicsemi.android.service.profile.ServiceApi
import no.nordicsemi.android.service.profile.StateReason
import no.nordicsemi.android.toolbox.profile.ProfileDestinationId
import no.nordicsemi.android.toolbox.profile.R
import no.nordicsemi.android.toolbox.profile.repository.DeviceRepository
import no.nordicsemi.android.ui.view.internal.DisconnectReason
import no.nordicsemi.kotlin.ble.client.android.Peripheral
import no.nordicsemi.kotlin.ble.core.ConnectionState
import timber.log.Timber
@@ -148,8 +145,7 @@ internal class ProfileViewModel @Inject constructor(
isAlreadyConnected: Boolean
) {
// Drop the first default state (Closed) before connection.
job = api.getConnectionState(deviceAddress)
?.drop(if (isAlreadyConnected) 0 else 1)
job = api.connectionState(deviceAddress)
?.onEach { connectionState ->
if (peripheral == null) peripheral = api.getPeripheralById(address)
when (connectionState) {
@@ -167,34 +163,24 @@ internal class ProfileViewModel @Inject constructor(
}
is ConnectionState.Disconnected -> {
_deviceState.update {
DeviceConnectionState.Disconnected(
peripheral,
StateReason(connectionState.reason)
)
}.also {
// Remove the analytics logged profiles for the disconnected device.
deviceRepository.removeLoggedProfile(deviceAddress)
}
}
ConnectionState.Closed -> {
unbindService()
api.disconnectionReason.onEach { reason ->
if (reason != null) {
_deviceState.update {
DeviceConnectionState.Disconnected(peripheral, reason)
}
} else {
_deviceState.update {
DeviceConnectionState.Disconnected(
peripheral,
CustomReason(DisconnectReason.UNKNOWN)
)
}
// If disconnected reason is null, it means that the connection was never initiated.
if (connectionState.reason == null) {
_deviceState.update {
DeviceConnectionState.Idle
}
}.launchIn(viewModelScope)
job?.cancel()
return@onEach
} else {
_deviceState.update {
DeviceConnectionState.Disconnected(
peripheral,
StateReason(connectionState.reason!!)
)
}.also {
// Remove the analytics logged profiles for the disconnected device.
deviceRepository.removeLoggedProfile(deviceAddress)
}
job?.cancel()
}
}
ConnectionState.Connecting -> {

View File

@@ -50,7 +50,7 @@ dependencyResolutionManagement {
}
versionCatalogs {
create("libs") {
from("no.nordicsemi.android.gradle:version-catalog:2.9-1")
from("no.nordicsemi.android.gradle:version-catalog:2.9-2")
}
}
}
@@ -69,9 +69,9 @@ include(":profile_data")
include(":profile_manager")
include(":permissions-ranging")
if (file("../Android-Common-Libraries").exists()) {
includeBuild("../Android-Common-Libraries")
}
//if (file("../Android-Common-Libraries").exists()) {
// includeBuild("../Android-Common-Libraries")
//}
//
//if (file("../Kotlin-BLE-Library").exists()) {
// includeBuild("../Kotlin-BLE-Library")