This commit is contained in:
lash404 committed 2026-10-28 08:17:47 +01:00
1 parent f54948b1a2
commit b1d89fbd08
6 files changed
+31 -51

No files matched your search

+1 -5
View File
@@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/>
<application <application
@@ -18,12 +17,9 @@
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/Theme.SmartWatchAndroid"> android:theme="@style/Theme.SmartWatchAndroid">
<service
android:name=".BluetoothForegroundService"
android:foregroundServiceType="connectedDevice"
android:exported="false" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:screenOrientation="portrait"
android:exported="true" android:exported="true"
android:theme="@style/Theme.SmartWatchAndroid" android:theme="@style/Theme.SmartWatchAndroid"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
@@ -14,9 +14,8 @@ import android.os.Build
import android.util.Log import android.util.Log
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.compose.runtime.mutableStateOf
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import com.example.smart_watch_android.MainActivity
import com.example.smart_watch_android.ViewModel
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@@ -27,15 +26,15 @@ import java.time.format.DateTimeFormatter
import java.util.UUID import java.util.UUID
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
class BleManager(private val context: Context, val viewModel: ViewModel) { class BleManager(private val context: Context) {
//var deviceAddress = "10:BD:A3:8F:01:0E" //var deviceAddress = "10:BD:A3:8F:01:0E"
val devices = mutableListOf<Devices>() var devices = mutableListOf<Devices>()
var isConnected = mutableStateOf(false)
val currentDate: LocalDate? = LocalDate.now() val currentDate: LocalDate? = LocalDate.now()
private val deviceUUIDs = DeviceUUIDs private val deviceUUIDs = DeviceUUIDs
private var bluetoothGatt: BluetoothGatt? = null private var bluetoothGatt: BluetoothGatt? = null
private var bluetoothManager: BluetoothManager? = null private var bluetoothManager: BluetoothManager? = null
private var bluetoothAdapter: BluetoothAdapter? = null private var bluetoothAdapter: BluetoothAdapter? = null
var deviceAddress: String = "" var deviceAddress: String = ""
@@ -47,7 +46,7 @@ class BleManager(private val context: Context, val viewModel: ViewModel) {
Log.d("ESP32_BLE", "Connected! Start discoverServices()...") Log.d("ESP32_BLE", "Connected! Start discoverServices()...")
gatt.discoverServices() gatt.discoverServices()
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
viewModel.setDeviceConection(false) isConnected.value = false
gatt.close() gatt.close()
bluetoothGatt = null bluetoothGatt = null
@@ -55,14 +54,14 @@ class BleManager(private val context: Context, val viewModel: ViewModel) {
} }
} else { } else {
Log.d("ESP32_BLE", "error in onConnectionStateChange! Status-Code: $status") Log.d("ESP32_BLE", "error in onConnectionStateChange! Status-Code: $status")
viewModel.setDeviceConection(false) isConnected.value = false
} }
} }
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS) { if (status == BluetoothGatt.GATT_SUCCESS) {
viewModel.setDeviceConection(true)
Log.d("ESP32_BLE", "connected successfully.") Log.d("ESP32_BLE", "connected successfully.")
isConnected.value = true
} }
} }
} }
@@ -77,6 +76,7 @@ class BleManager(private val context: Context, val viewModel: ViewModel) {
checkAndRequestBluetoothPermissions() checkAndRequestBluetoothPermissions()
bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager?.adapter bluetoothAdapter = bluetoothManager?.adapter
devices = getDeviceList() as MutableList<Devices>
} }
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@@ -84,6 +84,7 @@ class BleManager(private val context: Context, val viewModel: ViewModel) {
bluetoothAdapter?.bondedDevices?.forEach { device -> bluetoothAdapter?.bondedDevices?.forEach { device ->
devices.add(Devices(deviceName = device.name, deviceMac = device.address)) devices.add(Devices(deviceName = device.name, deviceMac = device.address))
} }
Log.d("devices","$devices")
return devices return devices
} }
@@ -116,7 +117,6 @@ class BleManager(private val context: Context, val viewModel: ViewModel) {
Log.d("ESP32_BLE", "error: Bluetooth is not supported!") Log.d("ESP32_BLE", "error: Bluetooth is not supported!")
return return
} }
try { try {
val device = bluetoothAdapter!!.getRemoteDevice(deviceAddress) val device = bluetoothAdapter!!.getRemoteDevice(deviceAddress)
@@ -13,19 +13,19 @@ import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BleManager
import com.example.smart_watch_android.Screens.AppNavigation import com.example.smart_watch_android.Screens.AppNavigation
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
lateinit var bleManager: BleManager lateinit var bleManager: BleManager
private val viewModel: ViewModel by viewModels()
@RequiresApi(Build.VERSION_CODES.S) @RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?,) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
bleManager = BleManager(this, viewModel) bleManager = BleManager(this)
bleManager.init() bleManager.init()
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
@@ -34,7 +34,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background color = MaterialTheme.colorScheme.background
) { ) {
AppNavigation(bleManager = bleManager, viewModel = viewModel) AppNavigation(bleManager = bleManager)
} }
} }
} }
@@ -4,22 +4,17 @@ import android.Manifest
import androidx.annotation.RequiresPermission import androidx.annotation.RequiresPermission
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BleManager
import com.example.smart_watch_android.ViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable @Composable
fun AppNavigation(bleManager: BleManager, viewModel: ViewModel) { fun AppNavigation(bleManager: BleManager) {
val navController = rememberNavController() val navController = rememberNavController()
val isConnected by viewModel.isDeviceConnected.collectAsState() LaunchedEffect(bleManager.isConnected) {
if (bleManager.isConnected.value) {
LaunchedEffect(viewModel.isConnected) {
if (isConnected) {
navController.navigate("control_panel") { navController.navigate("control_panel") {
popUpTo("connect") { inclusive = true } popUpTo("connect") { inclusive = true }
} }
@@ -29,7 +24,7 @@ fun AppNavigation(bleManager: BleManager, viewModel: ViewModel) {
} }
} }
} }
val startDestination = if (isConnected) { val startDestination = if (bleManager.isConnected.value) {
"control_panel" "control_panel"
} else { } else {
"connect" "connect"
@@ -42,8 +37,7 @@ fun AppNavigation(bleManager: BleManager, viewModel: ViewModel) {
// Connect Screen // Connect Screen
composable("connect") { composable("connect") {
ConnectScreen( ConnectScreen(
bleManager = bleManager, bleManager = bleManager
viewModel = viewModel
) )
} }
@@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
@@ -31,14 +30,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.smart_watch_android.BLE.BleManager import com.example.smart_watch_android.BLE.BleManager
import com.example.smart_watch_android.ViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT) @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable @Composable
fun ConnectScreen(bleManager: BleManager, viewModel: ViewModel) { fun ConnectScreen(bleManager: BleManager) {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
var selectedDevice by remember { mutableStateOf("device") } var selectedDevice by remember { mutableStateOf("device") }
val devices = bleManager.getDeviceList()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -47,6 +44,10 @@ fun ConnectScreen(bleManager: BleManager, viewModel: ViewModel) {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) )
{ {
Box(
modifier = Modifier
.padding(16.dp)
) {
Button( Button(
onClick = { expanded = !expanded }, onClick = { expanded = !expanded },
shape = RoundedCornerShape(4.dp), shape = RoundedCornerShape(4.dp),
@@ -56,9 +57,11 @@ fun ConnectScreen(bleManager: BleManager, viewModel: ViewModel) {
} }
DropdownMenu( DropdownMenu(
expanded = expanded, expanded = expanded,
onDismissRequest = { expanded = false } onDismissRequest = { expanded = false },
modifier = Modifier
.width(400.dp)
) { ) {
devices.forEach { item -> bleManager.devices.forEach { item ->
DropdownMenuItem( DropdownMenuItem(
text = { Text(item.deviceName) }, text = { Text(item.deviceName) },
onClick = { onClick = {
@@ -70,6 +73,9 @@ fun ConnectScreen(bleManager: BleManager, viewModel: ViewModel) {
) )
} }
} }
}
Spacer(modifier = Modifier.height(64.dp)) Spacer(modifier = Modifier.height(64.dp))
@@ -1,16 +0,0 @@
package com.example.smart_watch_android
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class ViewModel : ViewModel() {
var isConnected = MutableStateFlow(false)
val isDeviceConnected: StateFlow<Boolean> = isConnected.asStateFlow()
fun setDeviceConection(status: Boolean) {
isConnected.value = status
}
}