From 24db1bcc2b716e2e614a8324fc22ce0687719433 Mon Sep 17 00:00:00 2001 From: Sylwester Zielinski Date: Thu, 27 Apr 2023 16:00:31 +0200 Subject: [PATCH] Change approach for service & viewmodel state managment for all profiles --- .../nordicsemi/android/bps/view/BPSScreen.kt | 4 +-- .../android/bps/viewmodel/BPSViewModel.kt | 8 ----- .../android/cgms/data/CGMServiceData.kt | 3 +- .../android/cgms/repository/CGMRepository.kt | 29 +++++++++++++----- .../android/cgms/repository/CGMService.kt | 25 ++++++---------- .../nordicsemi/android/cgms/view/CGMScreen.kt | 7 ++--- .../android/cgms/viewmodel/CGMViewModel.kt | 15 +++++++++- .../android/csc/repository/CSCRepository.kt | 11 +------ .../android/csc/repository/CSCService.kt | 19 ++---------- .../nordicsemi/android/csc/view/CSCScreen.kt | 2 -- .../android/csc/viewmodel/CSCViewModel.kt | 2 +- .../android/gls/data/GLSServiceData.kt | 3 +- .../gls/main/viewmodel/GLSViewModel.kt | 14 ++------- .../android/hrs/data/HRSServiceData.kt | 3 +- .../android/hrs/service/HRSRepository.kt | 28 +++++++++++++---- .../android/hrs/service/HRSService.kt | 21 +++++-------- .../nordicsemi/android/hrs/view/HRSScreen.kt | 7 ++--- .../android/hrs/viewmodel/HRSViewModel.kt | 15 +++++++++- .../android/hts/repository/HTSRepository.kt | 8 ++--- .../android/hts/repository/HTSService.kt | 7 ++--- .../nordicsemi/android/hts/view/HTSScreen.kt | 2 -- .../android/prx/data/PRXServiceData.kt | 3 +- .../android/prx/repository/PRXRepository.kt | 29 ++++++++++++++---- .../android/prx/repository/PRXService.kt | 16 +++++----- .../nordicsemi/android/prx/view/PRXScreen.kt | 7 ++--- .../android/prx/viewmodel/PRXViewModel.kt | 10 ++++++- .../android/rscs/data/RSCSServiceData.kt | 3 +- .../android/rscs/repository/RSCSRepository.kt | 30 ++++++++++++++----- .../android/rscs/repository/RSCSService.kt | 21 +++++-------- .../android/rscs/view/RSCSScreen.kt | 7 ++--- .../android/rscs/viewmodel/RSCSViewModel.kt | 9 +++++- .../android/uart/data/UARTServiceData.kt | 3 +- .../android/uart/repository/UARTRepository.kt | 28 +++++++++++++---- .../android/uart/repository/UARTService.kt | 21 +++++-------- .../android/uart/view/UARTScreen.kt | 6 ++-- .../nordicsemi/android/uart/view/UARTState.kt | 3 +- .../android/uart/viewmodel/UARTViewModel.kt | 16 ++++++++-- 37 files changed, 244 insertions(+), 201 deletions(-) diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSScreen.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSScreen.kt index 8fd0a5d9..dbb647b8 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSScreen.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/view/BPSScreen.kt @@ -77,9 +77,7 @@ fun BPSScreen() { .verticalScroll(rememberScrollState()) .padding(16.dp) ) { - if (state.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.result.connectionState?.state) { + when (state.result.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> DeviceConnectingView { NavigateUpButton(navigateUp) } GattConnectionState.STATE_DISCONNECTED, diff --git a/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt b/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt index a6d3b454..7eb8da48 100644 --- a/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt +++ b/profile_bps/src/main/java/no/nordicsemi/android/bps/viewmodel/BPSViewModel.kt @@ -128,11 +128,9 @@ internal class BPSViewModel @Inject constructor( .onEach { onDataUpdate(it) } .onEach { stopIfDisconnected(it.state) } .onEach { logAnalytics(it.state) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(viewModelScope) if (!client.isConnected) { - _state.value = _state.value.copy(deviceName = device.name) return@launch } @@ -142,12 +140,6 @@ internal class BPSViewModel @Inject constructor( .launchIn(viewModelScope) } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED) { - _state.value = _state.value.copy(deviceName = device.name) - } - } - private suspend fun configureGatt(services: BleGattServices) { val bpsService = services.findService(BPS_SERVICE_UUID)!! val bpmCharacteristic = bpsService.findCharacteristic(BPM_CHARACTERISTIC_UUID)!! diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMServiceData.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMServiceData.kt index 2307c447..3cf495f6 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMServiceData.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/data/CGMServiceData.kt @@ -8,8 +8,7 @@ internal data class CGMServiceData( val records: List = emptyList(), val batteryLevel: Int? = null, val connectionState: GattConnectionStateWithStatus? = null, - val requestStatus: RequestStatus = RequestStatus.IDLE, - val deviceName: String? = null + val requestStatus: RequestStatus = RequestStatus.IDLE ) data class CGMRecordWithSequenceNumber( diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt index 24d76fb3..14715bef 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMRepository.kt @@ -32,7 +32,6 @@ package no.nordicsemi.android.cgms.repository import android.content.Context -import android.util.Log import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow @@ -74,6 +73,23 @@ class CGMRepository @Inject constructor( val hasRecords = data.value.records.isNotEmpty() val highestSequenceNumber = data.value.records.maxOfOrNull { it.sequenceNumber } ?: -1 + private var isOnScreen = false + private var isServiceRunning = false + + fun setOnScreen(isOnScreen: Boolean) { + this.isOnScreen = isOnScreen + + if (shouldClean()) clean() + } + + fun setServiceRunning(serviceRunning: Boolean) { + this.isServiceRunning = serviceRunning + + if (shouldClean()) clean() + } + + private fun shouldClean() = !isOnScreen && !isServiceRunning + fun launch(device: ServerDevice) { serviceManager.startService(CGMService::class.java, device) } @@ -102,16 +118,15 @@ class CGMRepository @Inject constructor( _loggerEvent.tryEmit(OpenLoggerEvent()) } - fun onInitComplete(device: ServerDevice) { - _data.value = _data.value.copy(deviceName = device.name) - } - fun clear() { _data.value = _data.value.copy(records = emptyList()) } - fun release() { - _data.value = CGMServiceData() + fun disconnect() { _stopEvent.tryEmit(DisconnectAndStopEvent()) } + + fun clean() { + _data.value = CGMServiceData() + } } diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt index e43cf74f..03cb77c4 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/repository/CGMService.kt @@ -104,11 +104,11 @@ internal class CGMService : NotificationService() { private lateinit var recordAccessControlPointCharacteristic: BleGattCharacteristic - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) + repository.setServiceRunning(true) + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! startGattClient(device) @@ -146,22 +146,19 @@ internal class CGMService : NotificationService() { .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(lifecycleScope) if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } client.discoverServices() .filterNotNull() - .onEach { configureGatt(it, device) } + .onEach { configureGatt(it) } .launchIn(lifecycleScope) } - private suspend fun configureGatt(services: BleGattServices, device: ServerDevice) { + private suspend fun configureGatt(services: BleGattServices) { val cgmService = services.findService(CGMS_SERVICE_UUID)!! val statusCharacteristic = cgmService.findCharacteristic(CGM_STATUS_UUID)!! val featureCharacteristic = cgmService.findCharacteristic(CGM_FEATURE_UUID)!! @@ -232,9 +229,6 @@ internal class CGMService : NotificationService() { if (sessionStartTime == 0L) { opsControlPointCharacteristic.write(CGMSpecificOpsControlPointData.startSession(secured).value!!) } - - hasBeenInitialized = true - repository.onInitComplete(device) } private fun onAccessControlPointDataReceived(data: RecordAccessControlPointData) = lifecycleScope.launch { @@ -317,13 +311,12 @@ internal class CGMService : NotificationService() { } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED && !hasBeenInitialized) { - repository.onInitComplete(device) - } - } - private fun disconnect() { client.disconnect() } + + override fun onDestroy() { + super.onDestroy() + repository.setServiceRunning(false) + } } diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMScreen.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMScreen.kt index 2e02bba0..994b42e8 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMScreen.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/view/CGMScreen.kt @@ -55,13 +55,14 @@ import no.nordicsemi.android.ui.view.ProfileAppBar fun CGMScreen() { val viewModel: CGMViewModel = hiltViewModel() val state = viewModel.state.collectAsState().value + val deviceName = viewModel.deviceName.collectAsState().value val navigateUp = { viewModel.onEvent(NavigateUp) } Scaffold( topBar = { ProfileAppBar( - deviceName = state.deviceName, + deviceName = deviceName, connectionState = state.connectionState, title = R.string.cgms_title, navigateUp = navigateUp, @@ -76,9 +77,7 @@ fun CGMScreen() { .verticalScroll(rememberScrollState()) .padding(16.dp) ) { - if (state.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.connectionState?.state) { + when (state.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> DeviceConnectingView { NavigateUpButton(navigateUp) } diff --git a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMViewModel.kt b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMViewModel.kt index abe520d8..b5a93b59 100644 --- a/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMViewModel.kt +++ b/profile_cgms/src/main/java/no/nordicsemi/android/cgms/viewmodel/CGMViewModel.kt @@ -35,6 +35,8 @@ import android.os.ParcelUuid import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -66,7 +68,12 @@ internal class CGMViewModel @Inject constructor( val state = repository.data + private val _deviceName = MutableStateFlow(null) + val deviceName = _deviceName.asStateFlow() + init { + repository.setOnScreen(true) + viewModelScope.launch { if (repository.isRunning.firstOrNull() == false) { requestBluetoothDevice() @@ -105,6 +112,7 @@ internal class CGMViewModel @Inject constructor( } private fun onDeviceSelected(device: ServerDevice) { + _deviceName.value = device.name repository.launch(device) } @@ -113,6 +121,11 @@ internal class CGMViewModel @Inject constructor( } private fun disconnect() { - repository.release() + repository.disconnect() + } + + override fun onCleared() { + super.onCleared() + repository.setOnScreen(false) } } diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt index 94544f15..d14b1c64 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCRepository.kt @@ -77,14 +77,6 @@ class CSCRepository @Inject constructor( serviceManager.startService(CSCService::class.java, device) } - fun onInitComplete(device: ServerDevice) { - Log.d("AAATESTAAA", "onInitComplete: ${data.value}") - if (_data.value.deviceName == null) { - Log.d("AAATESTAAA", "AAA") - _data.value = _data.value.copy(deviceName = device.name) - } - } - internal fun setSpeedUnit(speedUnit: SpeedUnit) { _data.value = _data.value.copy(speedUnit = speedUnit) } @@ -109,8 +101,7 @@ class CSCRepository @Inject constructor( _loggerEvent.tryEmit(OpenLoggerEvent()) } - fun release() { - Log.d("AAATESTAAA", "release: ${data.value}") + fun disconnect() { _data.value = CSCServiceData() _stopEvent.tryEmit(DisconnectAndStopEvent()) } diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt index 5e21dd1d..de72c23e 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/repository/CSCService.kt @@ -73,8 +73,6 @@ internal class CSCService : NotificationService() { private lateinit var client: BleGattClient - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) @@ -102,22 +100,19 @@ internal class CSCService : NotificationService() { .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(lifecycleScope) if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } client.discoverServices() .filterNotNull() - .onEach { configureGatt(it, device) } + .onEach { configureGatt(it) } .launchIn(lifecycleScope) } - private suspend fun configureGatt(services: BleGattServices, device: ServerDevice) { + private suspend fun configureGatt(services: BleGattServices) { val cscService = services.findService(CSC_SERVICE_UUID)!! val cscMeasurementCharacteristic = cscService.findCharacteristic(CSC_MEASUREMENT_CHARACTERISTIC_UUID)!! val batteryService = services.findService(BATTERY_SERVICE_UUID)!! @@ -133,9 +128,6 @@ internal class CSCService : NotificationService() { .mapNotNull { cscDataParser.parse(it, repository.wheelSize.value) } .onEach { repository.onCSCDataChanged(it) } .launchIn(lifecycleScope) - - hasBeenInitialized = true - repository.onInitComplete(device) } private fun stopIfDisconnected(connectionState: GattConnectionStateWithStatus) { @@ -144,13 +136,6 @@ internal class CSCService : NotificationService() { } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED && !hasBeenInitialized) { - hasBeenInitialized = true - repository.onInitComplete(device) - } - } - private fun disconnect() { client.disconnect() } diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/view/CSCScreen.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/view/CSCScreen.kt index 8ae5d0a3..662b2455 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/view/CSCScreen.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/view/CSCScreen.kt @@ -58,8 +58,6 @@ fun CSCScreen() { val viewModel: CSCViewModel = hiltViewModel() val state = viewModel.state.collectAsState().value - Log.d("AAATESTAAA", "State: ${state}") - val navigateUp = { viewModel.onEvent(NavigateUp) } Scaffold( diff --git a/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt b/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt index 47e61ed5..743647f4 100644 --- a/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt +++ b/profile_csc/src/main/java/no/nordicsemi/android/csc/viewmodel/CSCViewModel.kt @@ -115,7 +115,7 @@ internal class CSCViewModel @Inject constructor( } private fun disconnect() { - repository.release() + repository.disconnect() navigationManager.navigateUp() } } diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSServiceData.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSServiceData.kt index a5077951..8a75c921 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSServiceData.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/data/GLSServiceData.kt @@ -31,10 +31,9 @@ package no.nordicsemi.android.gls.data -import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionState import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus -import no.nordicsemi.android.kotlin.ble.profile.gls.data.GLSRecord import no.nordicsemi.android.kotlin.ble.profile.gls.data.GLSMeasurementContext +import no.nordicsemi.android.kotlin.ble.profile.gls.data.GLSRecord import no.nordicsemi.android.kotlin.ble.profile.gls.data.RequestStatus internal data class GLSServiceData( diff --git a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt index c10be870..0cb52598 100644 --- a/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt +++ b/profile_gls/src/main/java/no/nordicsemi/android/gls/main/viewmodel/GLSViewModel.kt @@ -163,17 +163,15 @@ internal class GLSViewModel @Inject constructor( client = device.connect(context, logger = logger) + client.waitForBonding() + client.connectionStateWithStatus .filterNotNull() .onEach { _state.value = _state.value.copyWithNewConnectionState(it) } .onEach { logAnalytics(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(viewModelScope) - client.waitForBonding() - if (!client.isConnected) { - _state.value = _state.value.copy(deviceName = device.name) return@launch } @@ -189,12 +187,6 @@ internal class GLSViewModel @Inject constructor( } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED) { - _state.value = _state.value.copy(deviceName = device.name) - } - } - private suspend fun configureGatt(services: BleGattServices, device: ServerDevice) { val glsService = services.findService(GLS_SERVICE_UUID)!! glucoseMeasurementCharacteristic = glsService.findCharacteristic(GM_CHARACTERISTIC)!! @@ -221,8 +213,6 @@ internal class GLSViewModel @Inject constructor( .mapNotNull { RecordAccessControlPointParser.parse(it) } .onEach { onAccessControlPointDataReceived(it) } .launchIn(viewModelScope) - - _state.value = _state.value.copy(deviceName = device.name) //prevents UI from appearing before BLE connection is set up } private fun onAccessControlPointDataReceived(data: RecordAccessControlPointData) = viewModelScope.launch { diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSServiceData.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSServiceData.kt index 89f5cebf..fc9d7fad 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSServiceData.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/data/HRSServiceData.kt @@ -40,8 +40,7 @@ internal data class HRSServiceData( val bodySensorLocation: Int? = null, val batteryLevel: Int? = null, val connectionState: GattConnectionStateWithStatus? = null, - val zoomIn: Boolean = false, - val deviceName: String? = null + val zoomIn: Boolean = false ) { val heartRates = data.map { it.heartRate } } diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt index 4de965a0..172de950 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSRepository.kt @@ -69,12 +69,25 @@ class HRSRepository @Inject constructor( val isRunning = data.map { it.connectionState?.state == GattConnectionState.STATE_CONNECTED } - fun launch(device: ServerDevice) { - serviceManager.startService(HRSService::class.java, device) + private var isOnScreen = false + private var isServiceRunning = false + + fun setOnScreen(isOnScreen: Boolean) { + this.isOnScreen = isOnScreen + + if (shouldClean()) clean() } - fun onInitComplete(device: ServerDevice) { - _data.value = _data.value.copy(deviceName = device.name) + fun setServiceRunning(serviceRunning: Boolean) { + this.isServiceRunning = serviceRunning + + if (shouldClean()) clean() + } + + private fun shouldClean() = !isOnScreen && !isServiceRunning + + fun launch(device: ServerDevice) { + serviceManager.startService(HRSService::class.java, device) } fun switchZoomIn() { @@ -101,8 +114,11 @@ class HRSRepository @Inject constructor( _loggerEvent.tryEmit(OpenLoggerEvent()) } - fun release() { - _data.value = HRSServiceData() + fun disconnect() { _stopEvent.tryEmit(DisconnectAndStopEvent()) } + + private fun clean() { + _data.value = HRSServiceData() + } } diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt index 18166de5..71cccdc0 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/service/HRSService.kt @@ -75,11 +75,11 @@ internal class HRSService : NotificationService() { private lateinit var client: BleGattClient - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) + repository.setServiceRunning(true) + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! startGattClient(device) @@ -104,14 +104,11 @@ internal class HRSService : NotificationService() { .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(lifecycleScope) client.waitForBonding() if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } @@ -140,9 +137,6 @@ internal class HRSService : NotificationService() { .mapNotNull { HRSDataParser.parse(it) } .onEach { repository.onHRSDataChanged(it) } .launchIn(lifecycleScope) - - hasBeenInitialized = true - repository.onInitComplete(device) } private fun stopIfDisconnected(connectionState: GattConnectionStateWithStatus) { @@ -151,13 +145,12 @@ internal class HRSService : NotificationService() { } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED && !hasBeenInitialized) { - repository.onInitComplete(device) - } - } - private fun disconnect() { client.disconnect() } + + override fun onDestroy() { + super.onDestroy() + repository.setServiceRunning(false) + } } diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSScreen.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSScreen.kt index d04d177b..d6bef795 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSScreen.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/view/HRSScreen.kt @@ -56,13 +56,14 @@ import no.nordicsemi.android.ui.view.ProfileAppBar fun HRSScreen() { val viewModel: HRSViewModel = hiltViewModel() val state = viewModel.state.collectAsState().value + val deviceName = viewModel.deviceName.collectAsState().value val navigateUp = { viewModel.onEvent(NavigateUpEvent) } Scaffold( topBar = { ProfileAppBar( - deviceName = state.deviceName, + deviceName = deviceName, connectionState = state.connectionState, title = R.string.hrs_title, navigateUp = navigateUp, @@ -77,9 +78,7 @@ fun HRSScreen() { .verticalScroll(rememberScrollState()) .padding(16.dp) ) { - if (state.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.connectionState?.state) { + when (state.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> DeviceConnectingView { NavigateUpButton(navigateUp) } GattConnectionState.STATE_DISCONNECTED, diff --git a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt index 3168334b..9ddfcffa 100644 --- a/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt +++ b/profile_hrs/src/main/java/no/nordicsemi/android/hrs/viewmodel/HRSViewModel.kt @@ -35,6 +35,8 @@ import android.os.ParcelUuid import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -65,7 +67,12 @@ internal class HRSViewModel @Inject constructor( val state = repository.data + private val _deviceName = MutableStateFlow(null) + val deviceName = _deviceName.asStateFlow() + init { + repository.setOnScreen(true) + viewModelScope.launch { if (repository.isRunning.firstOrNull() == false) { requestBluetoothDevice() @@ -95,6 +102,7 @@ internal class HRSViewModel @Inject constructor( } private fun onDeviceSelected(device: ServerDevice) { + _deviceName.value = device.name repository.launch(device) } @@ -112,7 +120,12 @@ internal class HRSViewModel @Inject constructor( } private fun disconnect() { - repository.release() + repository.disconnect() navigationManager.navigateUp() } + + override fun onCleared() { + super.onCleared() + repository.setOnScreen(false) + } } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt index 629a782a..93925047 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSRepository.kt @@ -73,10 +73,6 @@ class HTSRepository @Inject constructor( private var isOnScreen = false private var isServiceRunning = false - fun launch(device: ServerDevice) { - serviceManager.startService(HTSService::class.java, device) - } - fun setOnScreen(isOnScreen: Boolean) { this.isOnScreen = isOnScreen @@ -91,6 +87,10 @@ class HTSRepository @Inject constructor( private fun shouldClean() = !isOnScreen && !isServiceRunning + fun launch(device: ServerDevice) { + serviceManager.startService(HTSService::class.java, device) + } + internal fun setTemperatureUnit(temperatureUnit: TemperatureUnit) { _data.value = _data.value.copy(temperatureUnit = temperatureUnit) } diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt index 5d0c27e4..3c503085 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/repository/HTSService.kt @@ -74,8 +74,6 @@ internal class HTSService : NotificationService() { private lateinit var client: BleGattClient - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) @@ -104,7 +102,6 @@ internal class HTSService : NotificationService() { .launchIn(lifecycleScope) client.connectionStateWithStatus - .onEach { Log.d("AAATESTAAA", "Connection state: $it") } .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } @@ -116,11 +113,11 @@ internal class HTSService : NotificationService() { client.discoverServices() .filterNotNull() - .onEach { configureGatt(it, device) } + .onEach { configureGatt(it) } .launchIn(lifecycleScope) } - private suspend fun configureGatt(services: BleGattServices, device: ServerDevice) { + private suspend fun configureGatt(services: BleGattServices) { val htsService = services.findService(HTS_SERVICE_UUID)!! val htsMeasurementCharacteristic = htsService.findCharacteristic(HTS_MEASUREMENT_CHARACTERISTIC_UUID)!! val batteryService = services.findService(BATTERY_SERVICE_UUID)!! diff --git a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt index 2e1f9969..42705f31 100644 --- a/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt +++ b/profile_hts/src/main/java/no/nordicsemi/android/hts/view/HTSScreen.kt @@ -58,8 +58,6 @@ fun HTSScreen() { val state = viewModel.state.collectAsState().value val deviceName = viewModel.deviceName.collectAsState().value - Log.d("AAATESTAAA", "State: $state") - val navigateUp = { viewModel.onEvent(NavigateUp) } Scaffold( diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXServiceData.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXServiceData.kt index 48e2a373..90ff0f97 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXServiceData.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/data/PRXServiceData.kt @@ -11,8 +11,7 @@ data class PRXServiceData( val batteryLevel: Int? = null, val connectionState: GattConnectionStateWithStatus? = null, val connectionStatus: BleGattConnectionStatus? = null, - val isRemoteAlarm: Boolean = false, - val deviceName: String? = null + val isRemoteAlarm: Boolean = false ) { val isLinkLossDisconnected = connectionStatus?.isLinkLoss ?: false diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt index 183a53af..d0eab65b 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXRepository.kt @@ -70,12 +70,26 @@ class PRXRepository @Inject internal constructor( val isRunning = data.map { it.connectionState?.state == GattConnectionState.STATE_CONNECTED } - fun launch(device: ServerDevice) { - serviceManager.startService(PRXService::class.java, device) + private var isOnScreen = false + private var isServiceRunning = false + + fun setOnScreen(isOnScreen: Boolean) { + this.isOnScreen = isOnScreen + + if (shouldClean()) clean() } - fun onInitComplete(device: ServerDevice) { - _data.value = _data.value.copy(deviceName = device.name) + fun setServiceRunning(serviceRunning: Boolean) { + this.isServiceRunning = serviceRunning + + if (shouldClean()) clean() + } + + private fun shouldClean() = !isOnScreen && !isServiceRunning + + + fun launch(device: ServerDevice) { + serviceManager.startService(PRXService::class.java, device) } fun onConnectionStateChanged(connection: GattConnectionStateWithStatus) { @@ -106,9 +120,12 @@ class PRXRepository @Inject internal constructor( _loggerEvent.tryEmit(OpenLoggerEvent()) } - fun release() { - _data.value = PRXServiceData() + fun disconnect() { _remoteAlarmLevel.tryEmit(AlarmLevel.NONE) _stopEvent.tryEmit(DisconnectAndStopEvent()) } + + private fun clean() { + _data.value = PRXServiceData() + } } diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt index 96f668d3..062a447f 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/repository/PRXService.kt @@ -89,11 +89,11 @@ internal class PRXService : NotificationService() { private lateinit var alertLevelCharacteristic: BleGattCharacteristic - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) + repository.setServiceRunning(true) + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! startServer(device) @@ -175,8 +175,6 @@ internal class PRXService : NotificationService() { .launchIn(lifecycleScope) if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } @@ -204,9 +202,6 @@ internal class PRXService : NotificationService() { .launchIn(lifecycleScope) linkLossCharacteristic.write(AlertLevelInputParser.parse(AlarmLevel.HIGH)) - - hasBeenInitialized = true - repository.onInitComplete(device) } private suspend fun writeAlertLevel(alarmLevel: AlarmLevel) { @@ -217,7 +212,7 @@ internal class PRXService : NotificationService() { private fun stopIfDisconnected(connectionState: GattConnectionState, connectionStatus: BleGattConnectionStatus) { if (connectionState == GattConnectionState.STATE_DISCONNECTED && !connectionStatus.isLinkLoss) { server.stopServer() - repository.release() + repository.disconnect() stopSelf() } } @@ -226,4 +221,9 @@ internal class PRXService : NotificationService() { client.disconnect() server.stopServer() } + + override fun onDestroy() { + super.onDestroy() + repository.setServiceRunning(false) + } } diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXScreen.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXScreen.kt index 64140408..ab406789 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXScreen.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/view/PRXScreen.kt @@ -56,13 +56,14 @@ import no.nordicsemi.android.ui.view.ProfileAppBar fun PRXScreen() { val viewModel: PRXViewModel = hiltViewModel() val state = viewModel.state.collectAsState().value + val deviceName = viewModel.deviceName.collectAsState().value val navigateUp = { viewModel.onEvent(NavigateUpEvent) } Scaffold( topBar = { ProfileAppBar( - deviceName = state.deviceName, + deviceName = deviceName, connectionState = state.connectionState, title = R.string.prx_title, navigateUp = navigateUp, @@ -77,9 +78,7 @@ fun PRXScreen() { .verticalScroll(rememberScrollState()) .padding(16.dp) ) { - if (state.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.connectionState?.state) { + when (state.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> DeviceConnectingView { NavigateUpButton(navigateUp) } GattConnectionState.STATE_DISCONNECTED, diff --git a/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt b/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt index 53e86ce7..85fdf104 100644 --- a/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt +++ b/profile_prx/src/main/java/no/nordicsemi/android/prx/viewmodel/PRXViewModel.kt @@ -35,6 +35,8 @@ import android.os.ParcelUuid import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.launchIn @@ -71,7 +73,12 @@ internal class PRXViewModel @Inject constructor( val state = repository.data + private val _deviceName = MutableStateFlow(null) + val deviceName = _deviceName.asStateFlow() + init { + repository.setOnScreen(true) + viewModelScope.launch { if (repository.isRunning.firstOrNull() == false) { requestBluetoothDevice() @@ -123,11 +130,12 @@ internal class PRXViewModel @Inject constructor( private fun disconnect() { alarmHandler.pauseAlarm() navigationManager.navigateUp() - repository.release() + repository.disconnect() } override fun onCleared() { super.onCleared() alarmHandler.pauseAlarm() + repository.setOnScreen(false) } } diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceData.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceData.kt index 5ffb23b6..c5fbfaa3 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceData.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/data/RSCSServiceData.kt @@ -41,8 +41,7 @@ import no.nordicsemi.android.rscs.R internal data class RSCSServiceData( val data: RSCSData = RSCSData(), val batteryLevel: Int? = null, - val connectionState: GattConnectionStateWithStatus? = null, - val deviceName: String? = null + val connectionState: GattConnectionStateWithStatus? = null ) { @Composable fun displayActivity(): String { diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt index 10bc3004..6f6fdbc2 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSRepository.kt @@ -69,12 +69,25 @@ class RSCSRepository @Inject constructor( val isRunning = data.map { it.connectionState?.state == GattConnectionState.STATE_CONNECTED } - fun launch(device: ServerDevice) { - serviceManager.startService(RSCSService::class.java, device) + private var isOnScreen = false + private var isServiceRunning = false + + fun setOnScreen(isOnScreen: Boolean) { + this.isOnScreen = isOnScreen + + if (shouldClean()) clean() } - fun onInitComplete(device: ServerDevice) { - _data.value = _data.value.copy(deviceName = device.name) + fun setServiceRunning(serviceRunning: Boolean) { + this.isServiceRunning = serviceRunning + + if (shouldClean()) clean() + } + + private fun shouldClean() = !isOnScreen && !isServiceRunning + + fun launch(device: ServerDevice) { + serviceManager.startService(RSCSService::class.java, device) } fun onConnectionStateChanged(connectionState: GattConnectionStateWithStatus?) { @@ -93,9 +106,12 @@ class RSCSRepository @Inject constructor( _loggerEvent.tryEmit(OpenLoggerEvent()) } - fun release() { - logger = null - _data.value = RSCSServiceData() + fun disconnect() { _stopEvent.tryEmit(DisconnectAndStopEvent()) } + + private fun clean() { + logger = null + _data.value = RSCSServiceData() + } } diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt index 0056160d..17bae635 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/repository/RSCSService.kt @@ -73,11 +73,11 @@ internal class RSCSService : NotificationService() { private lateinit var client: BleGattClient - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) + repository.setServiceRunning(true) + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! startGattClient(device) @@ -102,12 +102,9 @@ internal class RSCSService : NotificationService() { .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(lifecycleScope) if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } @@ -132,9 +129,6 @@ internal class RSCSService : NotificationService() { .mapNotNull { RSCSDataParser.parse(it) } .onEach { repository.onRSCSDataChanged(it) } .launchIn(lifecycleScope) - - hasBeenInitialized = true - repository.onInitComplete(device) } private fun stopIfDisconnected(connectionState: GattConnectionStateWithStatus) { @@ -143,13 +137,12 @@ internal class RSCSService : NotificationService() { } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED && !hasBeenInitialized) { - repository.onInitComplete(device) - } - } - private fun disconnect() { client.disconnect() } + + override fun onDestroy() { + super.onDestroy() + repository.setServiceRunning(false) + } } diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSScreen.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSScreen.kt index d25e3057..63ccf344 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSScreen.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/view/RSCSScreen.kt @@ -56,13 +56,14 @@ import no.nordicsemi.android.ui.view.ProfileAppBar fun RSCSScreen() { val viewModel: RSCSViewModel = hiltViewModel() val state = viewModel.state.collectAsState().value + val deviceName = viewModel.deviceName.collectAsState().value val navigateUp = { viewModel.onEvent(NavigateUpEvent) } Scaffold( topBar = { ProfileAppBar( - deviceName = state.deviceName, + deviceName = deviceName, connectionState = state.connectionState, title = R.string.rscs_title, navigateUp = navigateUp, @@ -77,9 +78,7 @@ fun RSCSScreen() { .verticalScroll(rememberScrollState()) .padding(16.dp) ) { - if (state.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.connectionState?.state) { + when (state.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> DeviceConnectingView { NavigateUpButton(navigateUp) } GattConnectionState.STATE_DISCONNECTED, diff --git a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt index 57d912ac..46b6e379 100644 --- a/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt +++ b/profile_rscs/src/main/java/no/nordicsemi/android/rscs/viewmodel/RSCSViewModel.kt @@ -35,6 +35,8 @@ import android.os.ParcelUuid import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -64,6 +66,10 @@ internal class RSCSViewModel @Inject constructor( val state = repository.data + private val _deviceName = MutableStateFlow(null) + val deviceName = _deviceName.asStateFlow() + + init { viewModelScope.launch { if (repository.isRunning.firstOrNull() == false) { @@ -94,6 +100,7 @@ internal class RSCSViewModel @Inject constructor( } private fun onDeviceSelected(device: ServerDevice) { + _deviceName.value = device.name repository.launch(device) } @@ -106,7 +113,7 @@ internal class RSCSViewModel @Inject constructor( } private fun disconnect() { - repository.release() + repository.disconnect() navigationManager.navigateUp() } } diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceData.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceData.kt index 51df55e0..9fd18690 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceData.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/data/UARTServiceData.kt @@ -37,8 +37,7 @@ import no.nordicsemi.android.kotlin.ble.core.data.GattConnectionStateWithStatus internal data class UARTServiceData( val messages: List = emptyList(), val connectionState: GattConnectionStateWithStatus? = null, - val batteryLevel: Int? = null, - val deviceName: String? = null + val batteryLevel: Int? = null ) { val displayMessages = messages diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt index abcba7a8..979d9603 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTRepository.kt @@ -77,6 +77,23 @@ class UARTRepository @Inject internal constructor( val lastConfigurationName = configurationDataSource.lastConfigurationName + private var isOnScreen = false + private var isServiceRunning = false + + fun setOnScreen(isOnScreen: Boolean) { + this.isOnScreen = isOnScreen + + if (shouldClean()) clean() + } + + fun setServiceRunning(serviceRunning: Boolean) { + this.isServiceRunning = serviceRunning + + if (shouldClean()) clean() + } + + private fun shouldClean() = !isOnScreen && !isServiceRunning + fun launch(device: ServerDevice) { serviceManager.startService(UARTService::class.java, device) } @@ -97,10 +114,6 @@ class UARTRepository @Inject internal constructor( _data.value = _data.value.copy(messages = _data.value.messages + UARTRecord(value, UARTRecordType.INPUT)) } - fun onInitComplete(device: ServerDevice) { - _data.value = _data.value.copy(deviceName = device.name) - } - fun sendText(text: String, newLineChar: MacroEol) { _command.tryEmit(text.parseWithNewLineChar(newLineChar)) } @@ -124,8 +137,11 @@ class UARTRepository @Inject internal constructor( configurationDataSource.saveConfigurationName(name) } - fun release() { - _data.value = UARTServiceData() + fun disconnect() { _stopEvent.tryEmit(DisconnectAndStopEvent()) } + + private fun clean() { + _data.value = UARTServiceData() + } } diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt index ae63213c..b21958a6 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/repository/UARTService.kt @@ -78,11 +78,11 @@ internal class UARTService : NotificationService() { private lateinit var client: BleGattClient - private var hasBeenInitialized: Boolean = false - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { super.onStartCommand(intent, flags, startId) + repository.setServiceRunning(true) + val device = intent!!.getParcelableExtra(DEVICE_DATA)!! startGattClient(device) @@ -109,12 +109,9 @@ internal class UARTService : NotificationService() { .onEach { repository.onConnectionStateChanged(it) } .filterNotNull() .onEach { stopIfDisconnected(it) } - .onEach { unlockUiIfDisconnected(it, device) } .launchIn(lifecycleScope) if (!client.isConnected) { - hasBeenInitialized = true - repository.onInitComplete(device) return@launch } @@ -146,9 +143,6 @@ internal class UARTService : NotificationService() { .onEach { repository.onNewMessageSent(it) } .onEach { logger.log(10, "Sent: $it") } .launchIn(lifecycleScope) - - hasBeenInitialized = true - repository.onInitComplete(device) } private fun getWriteType(characteristic: BleGattCharacteristic): BleWriteType { @@ -165,13 +159,12 @@ internal class UARTService : NotificationService() { } } - private fun unlockUiIfDisconnected(connectionState: GattConnectionStateWithStatus, device: ServerDevice) { - if (connectionState.state == GattConnectionState.STATE_DISCONNECTED && !hasBeenInitialized) { - repository.onInitComplete(device) - } - } - private fun disconnect() { client.disconnect() } + + override fun onDestroy() { + super.onDestroy() + repository.setServiceRunning(false) + } } diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTScreen.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTScreen.kt index 6de05a50..33fb4c2a 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTScreen.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTScreen.kt @@ -68,7 +68,7 @@ fun UARTScreen() { Scaffold( topBar = { ProfileAppBar( - deviceName = state.uartManagerState.deviceName, + deviceName = state.deviceName, connectionState = state.uartManagerState.connectionState, title = R.string.uart_title, navigateUp = navigateUp, @@ -80,9 +80,7 @@ fun UARTScreen() { Column( modifier = Modifier.padding(it) ) { - if (state.uartManagerState.deviceName == null) { - DeviceConnectingView { NavigateUpButton(navigateUp) } - } else when (state.uartManagerState.connectionState?.state) { + when (state.uartManagerState.connectionState?.state) { null, GattConnectionState.STATE_CONNECTING -> PaddingBox { DeviceConnectingView { NavigateUpButton(navigateUp) } } GattConnectionState.STATE_DISCONNECTED, diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTState.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTState.kt index ff9fe7ad..4756d97f 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTState.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/view/UARTState.kt @@ -41,7 +41,8 @@ internal data class UARTViewState( val isConfigurationEdited: Boolean = false, val configurations: List = emptyList(), val uartManagerState: UARTServiceData = UARTServiceData(), - val isInputVisible: Boolean = true + val isInputVisible: Boolean = true, + val deviceName: String? = null ) { val showEditDialog: Boolean = editedPosition != null diff --git a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt index 30e79922..c29a1a74 100644 --- a/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt +++ b/profile_uart/src/main/java/no/nordicsemi/android/uart/viewmodel/UARTViewModel.kt @@ -91,6 +91,8 @@ internal class UARTViewModel @Inject constructor( val state = _state.asStateFlow() init { + repository.setOnScreen(true) + viewModelScope.launch { if (repository.isRunning.firstOrNull() == false) { requestBluetoothDevice() @@ -127,10 +129,15 @@ internal class UARTViewModel @Inject constructor( private fun handleResult(result: NavigationResult) { when (result) { is NavigationResult.Cancelled -> navigationManager.navigateUp() - is NavigationResult.Success -> repository.launch(result.value) + is NavigationResult.Success -> onDeviceSelected(result.value) } } + private fun onDeviceSelected(device: ServerDevice) { + _state.value = _state.value.copy(deviceName = device.name) + repository.launch(device) + } + fun onEvent(event: UARTViewEvent) { when (event) { is OnCreateMacro -> addNewMacro(event.macro) @@ -233,7 +240,12 @@ internal class UARTViewModel @Inject constructor( } private fun disconnect() { - repository.release() + repository.disconnect() navigationManager.navigateUp() } + + override fun onCleared() { + super.onCleared() + repository.setOnScreen(false) + } }