mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-08 17:24:31 +01:00
Add fixes to navigation.
This commit is contained in:
@@ -5,12 +5,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import no.nordicsemi.android.navigation.ForwardDestination
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.navigation.UUIDArgument
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class HomeViewModel @Inject constructor(
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
|
||||
@@ -24,9 +24,7 @@ class MainActivity : NordicActivity() {
|
||||
color = MaterialTheme.colorScheme.surface,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
NavigationView(
|
||||
HomeDestinations + ProfileDestinations + ScannerDestinations
|
||||
)
|
||||
NavigationView(HomeDestinations + ProfileDestinations + ScannerDestinations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import kotlinx.coroutines.flow.asStateFlow
|
||||
import no.nordicsemi.android.ble.BleManager
|
||||
import no.nordicsemi.android.log.ILogSession
|
||||
import no.nordicsemi.android.log.Logger
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
abstract class BleProfileService : Service() {
|
||||
@@ -47,9 +46,6 @@ abstract class BleProfileService : Service() {
|
||||
private val _status = MutableStateFlow(BleManagerStatus.CONNECTING)
|
||||
val status = _status.asStateFlow()
|
||||
|
||||
@Inject
|
||||
lateinit var bluetoothDeviceHolder: SelectedBluetoothDeviceHolder
|
||||
|
||||
/**
|
||||
* Returns a handler that is created in onCreate().
|
||||
* The handler may be used to postpone execution of some operations or to run them in UI thread.
|
||||
@@ -58,17 +54,6 @@ abstract class BleProfileService : Service() {
|
||||
|
||||
private var activityIsChangingConfiguration = false
|
||||
|
||||
/**
|
||||
* Returns the Bluetooth device object
|
||||
*
|
||||
* @return bluetooth device
|
||||
*/
|
||||
private val bluetoothDevice: BluetoothDevice by lazy {
|
||||
bluetoothDeviceHolder.device?.device ?: throw IllegalArgumentException(
|
||||
"No device associated with the application."
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the log session that can be used to append log entries. The method returns `null` if the nRF Logger app was not installed. It is safe to use logger when
|
||||
* [.onServiceStarted] has been called.
|
||||
@@ -119,7 +104,7 @@ abstract class BleProfileService : Service() {
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
super.onStartCommand(intent, flags, startId)
|
||||
|
||||
manager.connect(bluetoothDevice)
|
||||
manager.connect(intent!!.getParcelableExtra(DEVICE_DATA)!!)
|
||||
.useAutoConnect(shouldAutoConnect())
|
||||
.retry(3, 100)
|
||||
.enqueue()
|
||||
@@ -141,7 +126,6 @@ abstract class BleProfileService : Service() {
|
||||
// shutdown the manager
|
||||
manager.disconnect().enqueue()
|
||||
Logger.i(logSession, "Service destroyed")
|
||||
bluetoothDeviceHolder.forgetDevice()
|
||||
logSession = null
|
||||
handler = null
|
||||
}
|
||||
@@ -184,14 +168,6 @@ abstract class BleProfileService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the device address
|
||||
*
|
||||
* @return device address
|
||||
*/
|
||||
protected val deviceAddress: String
|
||||
get() = bluetoothDevice.address
|
||||
|
||||
/**
|
||||
* Returns `true` if the device is connected to the sensor.
|
||||
*
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package no.nordicsemi.android.service
|
||||
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SelectedBluetoothDeviceHolder @Inject constructor() {
|
||||
|
||||
var device: DiscoveredBluetoothDevice? = null
|
||||
private set
|
||||
|
||||
fun attachDevice(newDevice: DiscoveredBluetoothDevice) {
|
||||
device = newDevice
|
||||
}
|
||||
|
||||
fun forgetDevice() {
|
||||
device = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package no.nordicsemi.android.service
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import javax.inject.Inject
|
||||
|
||||
const val DEVICE_DATA = "device-data"
|
||||
|
||||
class ServiceManager @Inject constructor(
|
||||
@ApplicationContext
|
||||
private val context: Context
|
||||
) {
|
||||
|
||||
fun <T> startService(service: Class<T>, device: DiscoveredBluetoothDevice) {
|
||||
val intent = Intent(context, service).apply {
|
||||
putExtra(DEVICE_DATA, device)
|
||||
}
|
||||
context.startService(intent)
|
||||
}
|
||||
}
|
||||
@@ -16,20 +16,27 @@ import no.nordicsemi.android.bps.view.DisconnectEvent
|
||||
import no.nordicsemi.android.bps.view.DisplayDataState
|
||||
import no.nordicsemi.android.bps.view.LoadingState
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.navigation.ParcelableArgument
|
||||
import no.nordicsemi.android.navigation.SuccessDestinationResult
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import no.nordicsemi.ui.scanner.ScannerDestinationId
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class BPSViewModel @Inject constructor(
|
||||
private val bpsManager: BPSManager,
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||
private val repository: BPSRepository,
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val args
|
||||
get() = navigationManager.getResult(ScannerDestinationId)
|
||||
private val device
|
||||
get() = ((args as SuccessDestinationResult).argument as ParcelableArgument).value as DiscoveredBluetoothDevice
|
||||
|
||||
val state = repository.data.combine(repository.status) { data, status ->
|
||||
when (status) {
|
||||
BleManagerStatus.CONNECTING -> LoadingState
|
||||
@@ -70,7 +77,7 @@ internal class BPSViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun connectDevice() {
|
||||
bpsManager.connect(deviceHolder.device!!.device)
|
||||
bpsManager.connect(device.device)
|
||||
.useAutoConnect(false)
|
||||
.retry(3, 100)
|
||||
.enqueue()
|
||||
@@ -78,7 +85,6 @@ internal class BPSViewModel @Inject constructor(
|
||||
|
||||
private fun onDisconnectButtonClick() {
|
||||
bpsManager.disconnect().enqueue()
|
||||
deviceHolder.forgetDevice()
|
||||
repository.clear()
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ dependencies {
|
||||
implementation libs.nordic.log
|
||||
implementation libs.nordic.theme
|
||||
implementation libs.nordic.navigation
|
||||
implementation libs.nordic.ui.scanner
|
||||
|
||||
implementation libs.bundles.compose
|
||||
implementation libs.androidx.core
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package no.nordicsemi.android.csc.view
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import no.nordicsemi.android.csc.R
|
||||
import no.nordicsemi.android.csc.repository.CSCService
|
||||
import no.nordicsemi.android.csc.viewmodel.CSCViewModel
|
||||
import no.nordicsemi.android.theme.view.BackIconAppBar
|
||||
import no.nordicsemi.android.theme.view.DeviceConnectingView
|
||||
@@ -20,24 +16,13 @@ fun CSCScreen() {
|
||||
val viewModel: CSCViewModel = hiltViewModel()
|
||||
val state = viewModel.state.collectAsState().value
|
||||
|
||||
val context = LocalContext.current
|
||||
LaunchedEffect(Unit) {
|
||||
val intent = Intent(context, CSCService::class.java)
|
||||
context.startService(intent)
|
||||
}
|
||||
|
||||
CSCView(state) { viewModel.onEvent(it) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CSCView(state: CSCViewState, onEvent: (CSCViewEvent) -> Unit) {
|
||||
Column {
|
||||
BackIconAppBar(stringResource(id = R.string.csc_title)) {
|
||||
onEvent(OnDisconnectButtonClick)
|
||||
viewModel.onEvent(OnDisconnectButtonClick)
|
||||
}
|
||||
|
||||
when (state) {
|
||||
is DisplayDataState -> CSCContentView(state.data, onEvent)
|
||||
is DisplayDataState -> CSCContentView(state.data) { viewModel.onEvent(it) }
|
||||
LoadingState -> DeviceConnectingView()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
@@ -11,23 +11,37 @@ import kotlinx.coroutines.flow.stateIn
|
||||
import no.nordicsemi.android.csc.data.CSCRepository
|
||||
import no.nordicsemi.android.csc.data.DisconnectCommand
|
||||
import no.nordicsemi.android.csc.data.SetWheelSizeCommand
|
||||
import no.nordicsemi.android.csc.repository.CSCService
|
||||
import no.nordicsemi.android.csc.view.CSCViewEvent
|
||||
import no.nordicsemi.android.csc.view.DisplayDataState
|
||||
import no.nordicsemi.android.csc.view.LoadingState
|
||||
import no.nordicsemi.android.csc.view.OnDisconnectButtonClick
|
||||
import no.nordicsemi.android.csc.view.OnSelectedSpeedUnitSelected
|
||||
import no.nordicsemi.android.csc.view.OnWheelSizeSelected
|
||||
import no.nordicsemi.android.navigation.CancelDestinationResult
|
||||
import no.nordicsemi.android.navigation.ForwardDestination
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.navigation.ParcelableArgument
|
||||
import no.nordicsemi.android.navigation.SuccessDestinationResult
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.ServiceManager
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import no.nordicsemi.ui.scanner.ScannerDestinationId
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class CSCViewModel @Inject constructor(
|
||||
private val repository: CSCRepository,
|
||||
private val serviceManager: ServiceManager,
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val args
|
||||
get() = navigationManager.getResult(ScannerDestinationId)
|
||||
private val device
|
||||
get() = ((args as SuccessDestinationResult).argument as ParcelableArgument).value as DiscoveredBluetoothDevice
|
||||
|
||||
val state = repository.data.combine(repository.status) { data, status ->
|
||||
when (status) {
|
||||
BleManagerStatus.CONNECTING -> LoadingState
|
||||
@@ -37,6 +51,12 @@ internal class CSCViewModel @Inject constructor(
|
||||
}.stateIn(viewModelScope, SharingStarted.Lazily, LoadingState)
|
||||
|
||||
init {
|
||||
when (args) {
|
||||
CancelDestinationResult -> navigationManager.navigateUp()
|
||||
is SuccessDestinationResult -> serviceManager.startService(CSCService::class.java, device)
|
||||
null -> navigationManager.navigateTo(ForwardDestination(ScannerDestinationId))
|
||||
}.exhaustive
|
||||
|
||||
repository.status.onEach {
|
||||
if (it == BleManagerStatus.DISCONNECTED) {
|
||||
navigationManager.navigateUp()
|
||||
|
||||
@@ -3,19 +3,16 @@ package no.nordicsemi.dfu.data
|
||||
import android.content.Context
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import no.nordicsemi.android.dfu.DfuServiceInitiator
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import no.nordicsemi.dfu.repository.DFUService
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import javax.inject.Inject
|
||||
|
||||
class DFUManager @Inject constructor(
|
||||
@ApplicationContext
|
||||
private val context: Context,
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder
|
||||
private val context: Context
|
||||
) {
|
||||
|
||||
fun install(file: ZipFile) {
|
||||
val device = deviceHolder.device!!
|
||||
|
||||
fun install(file: ZipFile, device: DiscoveredBluetoothDevice) {
|
||||
val starter = DfuServiceInitiator(device.address())
|
||||
.setDeviceName(device.displayName())
|
||||
// .setKeepBond(keepBond)
|
||||
|
||||
@@ -8,13 +8,12 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
internal class DFURepository @Inject constructor(
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||
private val fileManger: DFUFileManager
|
||||
) {
|
||||
|
||||
@@ -27,10 +26,10 @@ internal class DFURepository @Inject constructor(
|
||||
private val _status = MutableStateFlow(BleManagerStatus.CONNECTING)
|
||||
val status = _status.asStateFlow()
|
||||
|
||||
fun setZipFile(file: Uri) {
|
||||
fun setZipFile(file: Uri, device: DiscoveredBluetoothDevice) {
|
||||
val currentState = _data.value as NoFileSelectedState
|
||||
_data.value = fileManger.createFile(file)?.let {
|
||||
FileReadyState(it, requireNotNull(deviceHolder.device))
|
||||
FileReadyState(it, device)
|
||||
} ?: currentState.copy(isError = true)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.navigation.ParcelableArgument
|
||||
import no.nordicsemi.android.navigation.SuccessDestinationResult
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
import no.nordicsemi.dfu.data.Completed
|
||||
import no.nordicsemi.dfu.data.DFUManager
|
||||
@@ -28,16 +30,24 @@ import no.nordicsemi.dfu.view.OnInstallButtonClick
|
||||
import no.nordicsemi.dfu.view.OnPauseButtonClick
|
||||
import no.nordicsemi.dfu.view.OnStopButtonClick
|
||||
import no.nordicsemi.dfu.view.OnZipFileSelected
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import no.nordicsemi.ui.scanner.ScannerDestinationId
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class DFUViewModel @Inject constructor(
|
||||
private val repository: DFURepository,
|
||||
private val progressManager: DFUProgressManager,
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||
private val dfuManager: DFUManager
|
||||
private val dfuManager: DFUManager,
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val args
|
||||
get() = navigationManager.getResult(ScannerDestinationId)
|
||||
private val device
|
||||
get() = ((args as SuccessDestinationResult).argument as ParcelableArgument).value as DiscoveredBluetoothDevice
|
||||
|
||||
|
||||
val state = repository.data.combine(progressManager.status) { state, status ->
|
||||
(state as? FileInstallingState)
|
||||
?.run { createInstallingStateWithNewStatus(state, status) }
|
||||
@@ -58,19 +68,18 @@ internal class DFUViewModel @Inject constructor(
|
||||
when (event) {
|
||||
OnDisconnectButtonClick -> closeScreen()
|
||||
OnInstallButtonClick -> {
|
||||
dfuManager.install(requireFile())
|
||||
dfuManager.install(requireFile(), device)
|
||||
repository.install()
|
||||
}
|
||||
OnPauseButtonClick -> closeScreen()
|
||||
OnStopButtonClick -> closeScreen()
|
||||
is OnZipFileSelected -> repository.setZipFile(event.file)
|
||||
is OnZipFileSelected -> repository.setZipFile(event.file, device)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun closeScreen() {
|
||||
repository.sendNewCommand(DisconnectCommand)
|
||||
repository.clear()
|
||||
deviceHolder.forgetDevice()
|
||||
}
|
||||
|
||||
private fun requireFile(): ZipFile {
|
||||
|
||||
@@ -15,20 +15,27 @@ import no.nordicsemi.android.gls.repository.GLSManager
|
||||
import no.nordicsemi.android.gls.view.DisplayDataState
|
||||
import no.nordicsemi.android.gls.view.LoadingState
|
||||
import no.nordicsemi.android.navigation.NavigationManager
|
||||
import no.nordicsemi.android.navigation.ParcelableArgument
|
||||
import no.nordicsemi.android.navigation.SuccessDestinationResult
|
||||
import no.nordicsemi.android.service.BleManagerStatus
|
||||
import no.nordicsemi.android.service.ConnectionObserverAdapter
|
||||
import no.nordicsemi.android.service.SelectedBluetoothDeviceHolder
|
||||
import no.nordicsemi.android.utils.exhaustive
|
||||
import no.nordicsemi.ui.scanner.DiscoveredBluetoothDevice
|
||||
import no.nordicsemi.ui.scanner.ScannerDestinationId
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class GLSViewModel @Inject constructor(
|
||||
private val glsManager: GLSManager,
|
||||
private val deviceHolder: SelectedBluetoothDeviceHolder,
|
||||
private val repository: GLSRepository,
|
||||
private val navigationManager: NavigationManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val args
|
||||
get() = navigationManager.getResult(ScannerDestinationId)
|
||||
private val device
|
||||
get() = ((args as SuccessDestinationResult).argument as ParcelableArgument).value as DiscoveredBluetoothDevice
|
||||
|
||||
val state = repository.data.combine(repository.status) { data, status ->
|
||||
when (status) {
|
||||
BleManagerStatus.CONNECTING -> LoadingState
|
||||
@@ -70,12 +77,10 @@ internal class GLSViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun connectDevice() {
|
||||
deviceHolder.device?.let {
|
||||
glsManager.connect(it.device)
|
||||
.useAutoConnect(false)
|
||||
.retry(3, 100)
|
||||
.enqueue()
|
||||
}
|
||||
glsManager.connect(device.device)
|
||||
.useAutoConnect(false)
|
||||
.retry(3, 100)
|
||||
.enqueue()
|
||||
}
|
||||
|
||||
private fun requestData(mode: WorkingMode) {
|
||||
@@ -87,7 +92,6 @@ internal class GLSViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun disconnect() {
|
||||
deviceHolder.forgetDevice()
|
||||
glsManager.disconnect().enqueue()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user