Fixed disconnection message display

This commit is contained in:
hiar
2025-08-27 16:11:21 +02:00
committed by Himali Aryal
parent 0b39290019
commit bb48d405da
6 changed files with 29 additions and 42 deletions

View File

@@ -1,14 +0,0 @@
package no.nordicsemi.android.service.profile
import no.nordicsemi.android.ui.view.internal.DisconnectReason
import no.nordicsemi.kotlin.ble.core.ConnectionState
/** Device disconnection reason. */
sealed interface DeviceDisconnectionReason
/** Includes the [ConnectionState.Disconnected.Reason]. */
data class StateReason(val reason: ConnectionState.Disconnected.Reason) : DeviceDisconnectionReason
/** Includes the custom made [DisconnectReason] to include other disconnection reasons which are not included in the [ConnectionState.Disconnected.Reason]. */
data class CustomReason(val reason: DisconnectReason) :
DeviceDisconnectionReason

View File

@@ -28,7 +28,6 @@ import no.nordicsemi.kotlin.ble.client.android.ConnectionPriority
import no.nordicsemi.kotlin.ble.client.android.Peripheral import no.nordicsemi.kotlin.ble.client.android.Peripheral
import no.nordicsemi.kotlin.ble.core.BondState import no.nordicsemi.kotlin.ble.core.BondState
import no.nordicsemi.kotlin.ble.core.ConnectionState import no.nordicsemi.kotlin.ble.core.ConnectionState
import no.nordicsemi.kotlin.ble.core.Manager
import no.nordicsemi.kotlin.ble.core.WriteType import no.nordicsemi.kotlin.ble.core.WriteType
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@@ -55,17 +54,6 @@ internal class ProfileService : NotificationService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
// Observe the Bluetooth state to handle global disconnection reasons.
centralManager.state.onEach { state ->
if (state == Manager.State.POWERED_OFF) {
_disconnectionEvent.value = ServiceApi.DisconnectionEvent(
"all_devices", // Generic address
CustomReason(DisconnectReason.BLUETOOTH_OFF)
)
// Optionally disconnect all devices
_devices.value.keys.forEach { disconnect(it) }
}
}.launchIn(lifecycleScope)
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@@ -131,7 +119,7 @@ internal class ProfileService : NotificationService() {
_disconnectionEvent.value = _disconnectionEvent.value =
ServiceApi.DisconnectionEvent( ServiceApi.DisconnectionEvent(
peripheral.address, peripheral.address,
StateReason(reason as ConnectionState.Disconnected.Reason) reason as ConnectionState.Disconnected.Reason
) )
_devices.update { it - peripheral.address } _devices.update { it - peripheral.address }
handleDisconnection(peripheral.address) handleDisconnection(peripheral.address)

View File

@@ -19,7 +19,10 @@ interface ServiceApi {
) )
/** A data class to represent a disconnection event. */ /** A data class to represent a disconnection event. */
data class DisconnectionEvent(val address: String, val reason: DeviceDisconnectionReason) data class DisconnectionEvent(
val address: String,
val reason: ConnectionState.Disconnected.Reason
)
/** /**
* A flow that emits the current state of all managed devices. * A flow that emits the current state of all managed devices.

View File

@@ -28,6 +28,7 @@ import no.nordicsemi.android.common.permissions.ble.RequireBluetooth
import no.nordicsemi.android.common.permissions.ble.RequireLocation import no.nordicsemi.android.common.permissions.ble.RequireLocation
import no.nordicsemi.android.common.permissions.notification.RequestNotificationPermission import no.nordicsemi.android.common.permissions.notification.RequestNotificationPermission
import no.nordicsemi.android.toolbox.lib.utils.Profile import no.nordicsemi.android.toolbox.lib.utils.Profile
import no.nordicsemi.android.toolbox.profile.data.displayMessage
import no.nordicsemi.android.toolbox.profile.view.battery.BatteryScreen import no.nordicsemi.android.toolbox.profile.view.battery.BatteryScreen
import no.nordicsemi.android.toolbox.profile.view.bps.BPSScreen import no.nordicsemi.android.toolbox.profile.view.bps.BPSScreen
import no.nordicsemi.android.toolbox.profile.view.cgms.CGMScreen import no.nordicsemi.android.toolbox.profile.view.cgms.CGMScreen
@@ -105,12 +106,20 @@ internal fun ProfileScreen() {
) )
is ProfileUiState.Disconnected -> { is ProfileUiState.Disconnected -> {
if (state.reason == null) {
// This is the initial state before connection attempt
// show device connecting view instead.
DeviceConnectingView(
modifier = Modifier.padding(16.dp)
)
} else {
DeviceDisconnectedView( DeviceDisconnectedView(
disconnectedReason = state.reason.toString(), disconnectedReason = state.reason.displayMessage(),
isMissingService = false, isMissingService = false,
modifier = Modifier.padding(16.dp), modifier = Modifier.padding(16.dp),
) { ) {
Button( Button(
modifier = Modifier.padding(16.dp),
onClick = { onEvent(ConnectionEvent.OnRetryClicked) }, onClick = { onEvent(ConnectionEvent.OnRetryClicked) },
) { ) {
@@ -118,6 +127,7 @@ internal fun ProfileScreen() {
} }
} }
} }
}
ProfileUiState.Loading -> DeviceConnectingView( ProfileUiState.Loading -> DeviceConnectingView(
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(16.dp)

View File

@@ -2,14 +2,14 @@ package no.nordicsemi.android.toolbox.profile.data
import no.nordicsemi.kotlin.ble.core.ConnectionState.Disconnected.Reason import no.nordicsemi.kotlin.ble.core.ConnectionState.Disconnected.Reason
fun toReason(reason: Reason): String = fun Reason.displayMessage(): String =
when (reason) { when (this) {
Reason.Cancelled -> "Connection was cancelled." Reason.Cancelled -> "Connection was cancelled."
Reason.LinkLoss -> "The device got out of range or has turned off." Reason.LinkLoss -> "The device got out of range or has turned off."
Reason.Success -> "Device disconnected successfully." Reason.Success -> "Device disconnected successfully."
Reason.TerminateLocalHost -> "Device disconnected by the local host." Reason.TerminateLocalHost -> "Device disconnected by the local host."
Reason.TerminatePeerUser -> "Device disconnected by the peer user." Reason.TerminatePeerUser -> "Device disconnected by the peer user."
is Reason.Timeout -> "Connection attempt timed out with ${reason.duration}." is Reason.Timeout -> "Connection attempt timed out with ${this.duration}."
is Reason.Unknown -> "Oops...! Connection went on a coffee break." is Reason.Unknown -> "Oops...! Connection went on a coffee break."
Reason.UnsupportedAddress -> "Device disconnected due to unsupported address." Reason.UnsupportedAddress -> "Device disconnected due to unsupported address."
Reason.InsufficientAuthentication -> "Device disconnected due to insufficient authentication." Reason.InsufficientAuthentication -> "Device disconnected due to insufficient authentication."

View File

@@ -1,7 +1,7 @@
package no.nordicsemi.android.toolbox.profile.viewmodel package no.nordicsemi.android.toolbox.profile.viewmodel
import no.nordicsemi.android.service.profile.DeviceDisconnectionReason
import no.nordicsemi.android.service.profile.ServiceApi import no.nordicsemi.android.service.profile.ServiceApi
import no.nordicsemi.kotlin.ble.core.ConnectionState
/** /**
* Events triggered by the user from the UI. * Events triggered by the user from the UI.
@@ -19,7 +19,7 @@ internal sealed interface ConnectionEvent {
*/ */
internal sealed interface ProfileUiState { internal sealed interface ProfileUiState {
data object Loading : ProfileUiState data object Loading : ProfileUiState
data class Disconnected(val reason: DeviceDisconnectionReason?) : ProfileUiState data class Disconnected(val reason: ConnectionState.Disconnected.Reason?) : ProfileUiState
data class Connected( data class Connected(
val deviceData: ServiceApi.DeviceData, val deviceData: ServiceApi.DeviceData,