Session closed message

This commit is contained in:
himalia416
2025-09-26 16:40:17 +02:00
committed by Himali Aryal
parent 46e8b8650e
commit feb131c655
5 changed files with 86 additions and 50 deletions

View File

@@ -26,6 +26,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import no.nordicsemi.android.toolbox.profile.data.RangingSessionAction
import no.nordicsemi.android.toolbox.profile.data.RangingSessionFailedReason
import no.nordicsemi.android.toolbox.profile.data.SessionClosedReason
import no.nordicsemi.android.toolbox.profile.data.UpdateRate
import timber.log.Timber
import java.util.UUID
@@ -51,7 +53,7 @@ class ChannelSoundingManager @Inject constructor(
object : RangingSession.Callback {
override fun onClosed(reason: Int) {
_rangingData.value =
RangingSessionAction.OnError(RangingSessionCloseReason.getReason(reason))
RangingSessionAction.OnError(RangingSessionFailedReason.getReason(reason))
// Unregister the callback to avoid memory leaks
rangingManager?.unregisterCapabilitiesCallback(rangingCapabilityCallback)
// Cleanup previous data
@@ -111,7 +113,8 @@ class ChannelSoundingManager @Inject constructor(
updateRate: UpdateRate = UpdateRate.NORMAL
) {
if (rangingManager == null) {
_rangingData.value = RangingSessionAction.OnError("RangingManager is not available")
_rangingData.value =
RangingSessionAction.OnError(SessionClosedReason.RANGING_NOT_AVAILABLE)
return
}
val setRangingUpdateRate = when (updateRate) {
@@ -177,17 +180,19 @@ class ChannelSoundingManager @Inject constructor(
}
} else {
_rangingData.value =
RangingSessionAction.OnError("Missing Ranging permission")
RangingSessionAction.OnError(
SessionClosedReason.MISSING_PERMISSION
)
return@RangingCapabilitiesCallback
}
} else {
_rangingData.value =
RangingSessionAction.OnError("Channel Sounding with required security level is not supported")
RangingSessionAction.OnError(SessionClosedReason.CS_SECURITY_NOT_AVAILABLE)
closeSession()
}
} else {
_rangingData.value =
RangingSessionAction.OnError("Channel Sounding Capabilities is not supported")
RangingSessionAction.OnError(SessionClosedReason.NOT_SUPPORTED)
closeSession()
}
@@ -221,7 +226,7 @@ class ChannelSoundingManager @Inject constructor(
}
}
} catch (e: Exception) {
_rangingData.value = RangingSessionAction.OnError(e.message ?: "Unknown error")
_rangingData.value = RangingSessionAction.OnError(SessionClosedReason.UNKNOWN)
}
}

View File

@@ -43,6 +43,7 @@ import no.nordicsemi.android.toolbox.profile.data.ChannelSoundingServiceData
import no.nordicsemi.android.toolbox.profile.data.ConfidenceLevel
import no.nordicsemi.android.toolbox.profile.data.RangingSessionAction
import no.nordicsemi.android.toolbox.profile.data.RangingTechnology
import no.nordicsemi.android.toolbox.profile.data.SessionClosedReason
import no.nordicsemi.android.toolbox.profile.data.UpdateRate
import no.nordicsemi.android.toolbox.profile.viewmodel.ChannelSoundingEvent
import no.nordicsemi.android.toolbox.profile.viewmodel.ChannelSoundingViewModel
@@ -165,14 +166,11 @@ private fun SessionClosed(
title = stringResource(R.string.channel_sounding),
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(stringResource(R.string.ranging_session_stopped))
}
Text(
stringResource(R.string.ranging_session_stopped),
modifier = Modifier.padding(8.dp),
textAlign = TextAlign.Center,
)
}
Button(
modifier = Modifier.padding(16.dp),
@@ -208,42 +206,21 @@ private fun SessionError(
title = stringResource(R.string.channel_sounding),
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
Text(
text = stringResource(sessionData.reason.toUiString()),
modifier = Modifier.padding(8.dp),
textAlign = TextAlign.Center,
)
}
if (sessionData.reason != SessionClosedReason.NOT_SUPPORTED ||
sessionData.reason != SessionClosedReason.RANGING_NOT_AVAILABLE) {
Button(
modifier = Modifier.padding(16.dp),
onClick = { onClickEvent(ChannelSoundingEvent.RestartRangingSession) },
) {
if (sessionData.reason.isNotEmpty()) {
Text(
stringResource(
R.string.ranging_session_closed_with_reason,
sessionData.reason
),
modifier = Modifier.padding(8.dp)
)
} else {
Text(
stringResource(R.string.ranging_session_closed),
modifier = Modifier.padding(8.dp)
)
}
Text(text = stringResource(id = R.string.reconnect))
}
}
Button(
modifier = Modifier.padding(16.dp),
onClick = { onClickEvent(ChannelSoundingEvent.RestartRangingSession) },
) {
Text(text = stringResource(id = R.string.reconnect))
}
}
}
@Preview(showBackground = true)
@Composable
private fun SessionError_Preview() {
NordicTheme {
SessionError(RangingSessionAction.OnError("Sample Error"), onClickEvent = {})
}
}

View File

@@ -2,7 +2,10 @@ package no.nordicsemi.android.toolbox.profile.view.channelSounding
import androidx.annotation.StringRes
import no.nordicsemi.android.toolbox.profile.R
import no.nordicsemi.android.toolbox.profile.data.RangingSessionFailedReason
import no.nordicsemi.android.toolbox.profile.data.RangingTechnology
import no.nordicsemi.android.toolbox.profile.data.SessionCloseReasonProvider
import no.nordicsemi.android.toolbox.profile.data.SessionClosedReason
import no.nordicsemi.android.toolbox.profile.data.UpdateRate
import no.nordicsemi.android.toolbox.profile.data.UpdateRate.FREQUENT
import no.nordicsemi.android.toolbox.profile.data.UpdateRate.INFREQUENT
@@ -38,3 +41,20 @@ internal fun RangingTechnology.toUiString(): Int {
}
@StringRes
internal fun SessionCloseReasonProvider.toUiString(): Int {
return when (this) {
SessionClosedReason.MISSING_PERMISSION -> R.string.cs_missing_permissions
SessionClosedReason.NOT_SUPPORTED -> R.string.channel_sounding_not_supported
SessionClosedReason.RANGING_NOT_AVAILABLE -> R.string.cs_ranging_not_available
SessionClosedReason.CS_SECURITY_NOT_AVAILABLE -> R.string.cs_security_not_available
SessionClosedReason.UNKNOWN -> R.string.cs_error_unknown
RangingSessionFailedReason.LOCAL_REQUEST -> R.string.cs_local_request
RangingSessionFailedReason.REMOTE_REQUEST -> R.string.cs_remote_request
RangingSessionFailedReason.UNSUPPORTED -> R.string.cs_params_unsupported
RangingSessionFailedReason.SYSTEM_POLICY -> R.string.cs_system_policy
RangingSessionFailedReason.NO_PEERS_FOUND -> R.string.cs_no_peers_found
RangingSessionFailedReason.UNKNOWN -> R.string.cs_error_unknown
}
}

View File

@@ -4,8 +4,6 @@
<string name="channel_sounding_not_supported">Channel Sounding is not supported on this Android version.</string>
<string name="initiating_ranging">Initiating ranging</string>
<string name="ranging_session_closed_with_reason"> Ranging session closed because of %s.</string>
<string name="ranging_session_closed">Ranging session closed.</string>
<string name="ranging_session_stopped">Ranging session stopped</string>
<string name="ranging_distance">Distance</string>
@@ -39,6 +37,17 @@
<string name="ranging_previous_measurement">Recent measurements</string>
<string name="ranging_details">Details</string>
<string name="cs_missing_permissions">Missing permissions.</string>
<string name="cs_ranging_not_available">Ranging service not available.</string>
<string name="cs_security_not_available">Channel Sounding with required security level is not supported. </string>
<string name="cs_error_unknown">Oops! Session just ghosted harder than your last Tinder date. Try reconnecting…</string>
<string name="cs_local_request">Session terminated by local request.</string>
<string name="cs_remote_request">Session terminated by remote peer.</string>
<string name="cs_peer_terminated">Peer terminated the session.</string>
<string name="cs_system_policy">Local system policy forced the session to close.</string>
<string name="cs_params_unsupported">Provided session parameters are not supported.</string>
<string name="cs_no_peers_found">No peers found.</string>
<string name="update_rate_confirm">Confirm</string>
<string name="update_rate_cancel">Cancel</string>
</resources>

View File

@@ -17,7 +17,7 @@ sealed interface RangingSessionAction {
val previousData: List<Float> = emptyList()
) : RangingSessionAction
data class OnError(val reason: String) : RangingSessionAction
data class OnError(val reason: SessionCloseReasonProvider) : RangingSessionAction
object OnClosed : RangingSessionAction
}
@@ -48,3 +48,28 @@ enum class RangingTechnology(val value: Int) {
fun from(value: Int): RangingTechnology? = entries.find { it.value == value }
}
}
enum class SessionClosedReason : SessionCloseReasonProvider {
MISSING_PERMISSION,
NOT_SUPPORTED,
RANGING_NOT_AVAILABLE,
CS_SECURITY_NOT_AVAILABLE,
UNKNOWN;
}
sealed interface SessionCloseReasonProvider
enum class RangingSessionFailedReason(val reason: Int):SessionCloseReasonProvider {
UNKNOWN(0),
LOCAL_REQUEST(1),
REMOTE_REQUEST(2),
UNSUPPORTED(3),
SYSTEM_POLICY(4),
NO_PEERS_FOUND(5), ;
companion object {
fun getReason(value: Int): RangingSessionFailedReason {
return entries.firstOrNull { it.reason == value } ?: UNKNOWN
}
}
}