refactor: move bluetooth state to settings view model

This commit is contained in:
Fritz Heiden 2025-03-25 14:43:18 +01:00
parent 0c1f4801c3
commit e3623cb128
5 changed files with 25 additions and 40 deletions

View File

@ -1,13 +1,11 @@
package com.example.tvcontroller package com.example.tvcontroller
import android.bluetooth.BluetoothAdapter
import android.content.ContentValues.TAG import android.content.ContentValues.TAG
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -30,11 +28,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.tvcontroller.services.BluetoothService import com.example.tvcontroller.services.BluetoothService
import com.example.tvcontroller.services.CameraService import com.example.tvcontroller.services.CameraService
import com.example.tvcontroller.services.DeviceService import com.example.tvcontroller.services.DeviceService
import com.example.tvcontroller.ui.AppViewModel
import com.example.tvcontroller.ui.views.CameraView import com.example.tvcontroller.ui.views.CameraView
import com.example.tvcontroller.ui.views.SettingsView import com.example.tvcontroller.ui.views.SettingsView
@ -43,13 +39,10 @@ class MainActivity : ComponentActivity() {
private lateinit var bluetoothService: BluetoothService private lateinit var bluetoothService: BluetoothService
private lateinit var deviceService: DeviceService private lateinit var deviceService: DeviceService
private lateinit var cameraService: CameraService private lateinit var cameraService: CameraService
private val appViewModel by viewModels<AppViewModel>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
bluetoothService = BluetoothService(this.applicationContext) bluetoothService = BluetoothService(this.applicationContext)
bluetoothService.onBluetoothStateChanged { state -> appViewModel.setBluetoothEnabled(state == BluetoothAdapter.STATE_ON) }
appViewModel.setBluetoothEnabled(bluetoothService.isBluetoothEnabled())
deviceService = DeviceService(this.applicationContext) deviceService = DeviceService(this.applicationContext)
cameraService = CameraService(this.applicationContext) cameraService = CameraService(this.applicationContext)
checkPermissions() checkPermissions()
@ -57,7 +50,6 @@ class MainActivity : ComponentActivity() {
setContent { setContent {
TVControllerTheme { TVControllerTheme {
TvControllerApp( TvControllerApp(
appViewModel = appViewModel,
bluetoothService = bluetoothService, bluetoothService = bluetoothService,
deviceService = deviceService deviceService = deviceService
) )
@ -75,8 +67,7 @@ class MainActivity : ComponentActivity() {
@Composable @Composable
fun TvControllerApp( fun TvControllerApp(
navController: NavHostController = rememberNavController(), navController: NavHostController = rememberNavController(),
appViewModel: AppViewModel = viewModel(), bluetoothService: BluetoothService,
bluetoothService: BluetoothService? = null,
deviceService: DeviceService deviceService: DeviceService
) { ) {
val backStackEntry by navController.currentBackStackEntryAsState() val backStackEntry by navController.currentBackStackEntryAsState()
@ -134,7 +125,10 @@ fun TvControllerApp(
RemoteScreen() RemoteScreen()
} }
composable(route = Screen.Settings.name) { composable(route = Screen.Settings.name) {
SettingsView(appViewModel = appViewModel, deviceService = deviceService) SettingsView(
deviceService = deviceService,
bluetoothService = bluetoothService
)
} }
} }
} }

View File

@ -1,15 +1,20 @@
package com.example.tvcontroller package com.example.tvcontroller
import android.bluetooth.BluetoothAdapter
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.example.tvcontroller.services.BluetoothService
import com.example.tvcontroller.services.DeviceService import com.example.tvcontroller.services.DeviceService
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class SettingsViewModel(private val deviceService: DeviceService) : ViewModel() { class SettingsViewModel(
private val deviceService: DeviceService,
private val bluetoothService: BluetoothService
) : ViewModel() {
var serverAddress by mutableStateOf(deviceService.getServerAddress()) var serverAddress by mutableStateOf(deviceService.getServerAddress())
private set private set
var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL) var deviceName by mutableStateOf(android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL)
@ -18,12 +23,17 @@ class SettingsViewModel(private val deviceService: DeviceService) : ViewModel()
private set private set
var connectionState by mutableStateOf(Settings.ConnectionState.Unregistered) var connectionState by mutableStateOf(Settings.ConnectionState.Unregistered)
private set private set
var bluetoothEnabled by mutableStateOf(bluetoothService.isBluetoothEnabled())
private set
init { init {
updateConnectionState() updateConnectionState()
viewModelScope.launch { viewModelScope.launch {
updateDeviceInfo() updateDeviceInfo()
} }
bluetoothService.onBluetoothStateChanged {
bluetoothEnabled = it == BluetoothAdapter.STATE_ON
}
} }
fun connect() { fun connect() {
@ -69,10 +79,11 @@ class SettingsViewModel(private val deviceService: DeviceService) : ViewModel()
companion object { companion object {
fun provideFactory( fun provideFactory(
deviceService: DeviceService, deviceService: DeviceService,
bluetoothService: BluetoothService,
) = object : ViewModelProvider.Factory { ) = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SettingsViewModel(deviceService) as T return SettingsViewModel(deviceService, bluetoothService) as T
} }
} }
} }

View File

@ -1,7 +0,0 @@
package com.example.tvcontroller.ui
import com.example.tvcontroller.Screen
data class AppUiState(
val currentScreen: Screen = Screen.Settings,
)

View File

@ -1,16 +0,0 @@
package com.example.tvcontroller.ui
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
class AppViewModel() : ViewModel() {
private var isBluetoothEnabled = mutableStateOf(false)
fun setBluetoothEnabled(enabled: Boolean) {
isBluetoothEnabled.value = enabled
}
fun isBluetoothEnabled(): Boolean {
return isBluetoothEnabled.value
}
}

View File

@ -19,13 +19,16 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.tvcontroller.R import com.example.tvcontroller.R
import com.example.tvcontroller.Settings import com.example.tvcontroller.Settings
import com.example.tvcontroller.SettingsViewModel import com.example.tvcontroller.SettingsViewModel
import com.example.tvcontroller.services.BluetoothService
import com.example.tvcontroller.services.DeviceService import com.example.tvcontroller.services.DeviceService
import com.example.tvcontroller.ui.AppViewModel
@Composable @Composable
fun SettingsView(deviceService: DeviceService, appViewModel: AppViewModel) { fun SettingsView(
deviceService: DeviceService,
bluetoothService: BluetoothService
) {
val viewModel = val viewModel =
viewModel<SettingsViewModel>(factory = SettingsViewModel.Companion.provideFactory(deviceService)) viewModel<SettingsViewModel>(factory = SettingsViewModel.provideFactory(deviceService, bluetoothService))
Column( Column(
modifier = Modifier modifier = Modifier
@ -76,7 +79,7 @@ fun SettingsView(deviceService: DeviceService, appViewModel: AppViewModel) {
text = stringResource(id = R.string.controller_settings_heading), text = stringResource(id = R.string.controller_settings_heading),
style = MaterialTheme.typography.headlineSmall style = MaterialTheme.typography.headlineSmall
) )
if (appViewModel.isBluetoothEnabled()) { if (viewModel.bluetoothEnabled) {
Text( Text(
text = "Controller settings: Bluetooth is enabled.", text = "Controller settings: Bluetooth is enabled.",
style = MaterialTheme.typography.bodyMedium style = MaterialTheme.typography.bodyMedium