fix: device name display
This commit is contained in:
parent
c86ef81c4a
commit
e168f08aa4
|
@ -79,16 +79,7 @@ fun SettingsList(viewModel: CarViewModel) {
|
|||
SettingConnectDeviceItem(viewModel)
|
||||
}
|
||||
item {
|
||||
ListItem(
|
||||
headlineContent = { Text("设备名称") },
|
||||
supportingContent = { Text("当前名称: Name") },
|
||||
trailingContent = {
|
||||
Icon(
|
||||
ImageVector.vectorResource(R.drawable.arrow_right_24),
|
||||
contentDescription = "设备名称"
|
||||
)
|
||||
}
|
||||
)
|
||||
SettingDeviceNameItem(viewModel)
|
||||
}
|
||||
item {
|
||||
ListItem(
|
||||
|
@ -180,3 +171,19 @@ fun SettingConnectDeviceItem(viewModel: CarViewModel) {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SettingDeviceNameItem(viewModel: CarViewModel) {
|
||||
val connectionInfoState by viewModel.connectionInfoState.collectAsState()
|
||||
|
||||
ListItem(
|
||||
headlineContent = { Text("设备名称") },
|
||||
supportingContent = { Text("当前名称: ${connectionInfoState.name}") },
|
||||
trailingContent = {
|
||||
Icon(
|
||||
ImageVector.vectorResource(R.drawable.arrow_right_24),
|
||||
contentDescription = "设备名称"
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ interface BluetoothRepository {
|
|||
fun observeLogs(): Flow<List<LogEntry>>
|
||||
fun clearLogs()
|
||||
val connectionState: StateFlow<ConnectionState>
|
||||
val deviceName: StateFlow<String?>
|
||||
val deviceAddress: StateFlow<String?>
|
||||
}
|
||||
|
||||
// 添加连接状态枚举
|
||||
|
@ -55,6 +57,9 @@ val serviceUUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
|
|||
val rxCharUUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
val txCharUUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
|
||||
|
||||
val deviceInfoServiceUUID = "0000180a-0000-1000-8000-00805f9b34fb"
|
||||
val deviceNameCharUUID = "00002a00-0000-1000-8000-00805f9b34fb"
|
||||
|
||||
// 蓝牙通信实现
|
||||
class BluetoothRepositoryImpl(
|
||||
private val context: Context,
|
||||
|
@ -80,6 +85,12 @@ class BluetoothRepositoryImpl(
|
|||
private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED)
|
||||
override val connectionState: StateFlow<ConnectionState> = _connectionState.asStateFlow()
|
||||
|
||||
private val _deviceName = MutableStateFlow<String?>(null)
|
||||
override val deviceName: StateFlow<String?> = _deviceName.asStateFlow()
|
||||
|
||||
private val _deviceAddress = MutableStateFlow<String?>(null)
|
||||
override val deviceAddress: StateFlow<String?> = _deviceAddress.asStateFlow()
|
||||
|
||||
private val scanCallback = object : ScanCallback() {
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||
val bleDevice = BleDevice(
|
||||
|
@ -132,7 +143,10 @@ class BluetoothRepositoryImpl(
|
|||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun connectToDevice(device: BluetoothDevice, callback: ((Boolean) -> Unit)? = null) {
|
||||
fun connectToDevice(
|
||||
device: BluetoothDevice,
|
||||
callback: ((Boolean, BluetoothDevice?) -> Unit)? = null
|
||||
) {
|
||||
_connectionState.value = ConnectionState.CONNECTING
|
||||
device.connectGatt(
|
||||
context,
|
||||
|
@ -164,21 +178,23 @@ class BluetoothRepositoryImpl(
|
|||
}
|
||||
}
|
||||
if (callback != null) {
|
||||
callback(true)
|
||||
callback(true, gatt.device)
|
||||
}
|
||||
_deviceAddress.value = gatt.device.address
|
||||
_deviceName.value = gatt.device.name ?: "未知设备"
|
||||
}
|
||||
|
||||
BluetoothProfile.STATE_CONNECTING -> {
|
||||
_connectionState.value = ConnectionState.CONNECTING
|
||||
if (callback != null) {
|
||||
callback(false)
|
||||
callback(false, null)
|
||||
}
|
||||
}
|
||||
|
||||
BluetoothProfile.STATE_DISCONNECTING -> {
|
||||
_connectionState.value = ConnectionState.DISCONNECTING
|
||||
if (callback != null) {
|
||||
callback(false)
|
||||
callback(false, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,8 +203,10 @@ class BluetoothRepositoryImpl(
|
|||
rxCharacteristic = null
|
||||
_connectionState.value = ConnectionState.DISCONNECTED
|
||||
if (callback != null) {
|
||||
callback(false)
|
||||
callback(false, null)
|
||||
}
|
||||
_deviceName.value = null
|
||||
_deviceAddress.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +214,15 @@ class BluetoothRepositoryImpl(
|
|||
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
|
||||
super.onServicesDiscovered(gatt, status)
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// 读取设备名称
|
||||
val genericService =
|
||||
gatt?.getService(UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"))
|
||||
val deviceNameChar =
|
||||
genericService?.getCharacteristic(UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb"))
|
||||
if (deviceNameChar != null) {
|
||||
gatt.readCharacteristic(deviceNameChar)
|
||||
}
|
||||
|
||||
gatt?.getService(UUID.fromString(serviceUUID))?.let { service ->
|
||||
bluetoothGatt = gatt
|
||||
rxCharacteristic =
|
||||
|
@ -213,6 +240,20 @@ class BluetoothRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicRead(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
value: ByteArray,
|
||||
status: Int
|
||||
) {
|
||||
super.onCharacteristicRead(gatt, characteristic, value, status)
|
||||
if (characteristic.uuid == UUID.fromString(deviceNameCharUUID)) {
|
||||
val deviceName = String(value)
|
||||
_deviceName.value = deviceName
|
||||
Log.d("DeviceName", "Device name: $deviceName")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicChanged(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
|
@ -222,6 +263,11 @@ class BluetoothRepositoryImpl(
|
|||
if (characteristic.uuid == UUID.fromString(txCharUUID)) {
|
||||
onReceivePacket(value)
|
||||
}
|
||||
if (characteristic.uuid == UUID.fromString(deviceNameCharUUID)) {
|
||||
val deviceName = String(value)
|
||||
_deviceName.value = deviceName
|
||||
_deviceAddress.value = gatt.device.address
|
||||
}
|
||||
}
|
||||
},
|
||||
TRANSPORT_LE
|
||||
|
@ -237,8 +283,8 @@ class BluetoothRepositoryImpl(
|
|||
context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
val device = bluetoothManager.adapter.getRemoteDevice(address)
|
||||
if (callback != null) {
|
||||
connectToDevice(device) { isConnected ->
|
||||
callback(isConnected, device)
|
||||
connectToDevice(device) { isConnected, deviceDetail ->
|
||||
callback(isConnected, deviceDetail ?: device)
|
||||
}
|
||||
} else {
|
||||
connectToDevice(device)
|
||||
|
@ -246,6 +292,28 @@ class BluetoothRepositoryImpl(
|
|||
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun setupDeviceNameNotification(gatt: BluetoothGatt) {
|
||||
val service = gatt.getService(UUID.fromString(deviceInfoServiceUUID))
|
||||
val characteristic = service?.getCharacteristic(UUID.fromString(deviceNameCharUUID))
|
||||
|
||||
characteristic?.let { char ->
|
||||
// 启用通知
|
||||
gatt.setCharacteristicNotification(char, true)
|
||||
|
||||
// 获取 descriptor 并写入通知使能值
|
||||
val descriptor =
|
||||
char.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
|
||||
descriptor?.let {
|
||||
it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
||||
gatt.writeDescriptor(it)
|
||||
}
|
||||
|
||||
// 同时也读取一次当前值
|
||||
gatt.readCharacteristic(char)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun sendCommand(command: ByteArray) {
|
||||
rxCharacteristic?.let { characteristic ->
|
||||
|
@ -321,7 +389,8 @@ class BluetoothRepositoryImpl(
|
|||
|
||||
private fun createInfraredState(irPinCount: Int, irData: UByte) = InfraredState(
|
||||
enable = true,
|
||||
statusList = irData.toString(2).padStart(irPinCount, '0').reversed().map { if (it == '1') 1u else 0u }
|
||||
statusList = irData.toString(2).padStart(irPinCount, '0').reversed()
|
||||
.map { if (it == '1') 1u else 0u }
|
||||
)
|
||||
|
||||
// 断开连接方法
|
||||
|
@ -330,6 +399,12 @@ class BluetoothRepositoryImpl(
|
|||
bluetoothGatt?.let { gatt ->
|
||||
_connectionState.value = ConnectionState.DISCONNECTING
|
||||
gatt.disconnect()
|
||||
gatt.close() // 重要:需要调用 close() 释放资源
|
||||
bluetoothGatt = null
|
||||
rxCharacteristic = null
|
||||
_deviceName.value = null
|
||||
_deviceAddress.value = null
|
||||
_connectionState.value = ConnectionState.DISCONNECTED
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import android.view.WindowManager
|
||||
import kotlinx.coroutines.flow.combine
|
||||
|
||||
|
||||
// 用例
|
||||
|
@ -82,20 +83,14 @@ class CarViewModel(
|
|||
fun startScan() = (repository as BluetoothRepositoryImpl).startScan()
|
||||
fun stopScan() = (repository as BluetoothRepositoryImpl).stopScan()
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun connectToDevice(device: BluetoothDevice) {
|
||||
(repository as BluetoothRepositoryImpl).connectToDevice(device) { isConnected ->
|
||||
if (isConnected) {
|
||||
updateDeviceInfo(device)
|
||||
}
|
||||
}
|
||||
(repository as BluetoothRepositoryImpl).connectToDevice(device)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun connectToDeviceByAddress(address: String) {
|
||||
(repository as BluetoothRepositoryImpl).connectToDeviceByAddress(address) { isConnected, device ->
|
||||
if (isConnected) {
|
||||
updateDeviceInfo(device)
|
||||
}
|
||||
}
|
||||
(repository as BluetoothRepositoryImpl).connectToDeviceByAddress(address)
|
||||
}
|
||||
|
||||
val carState: StateFlow<CarState> = repository.observeCarState()
|
||||
|
@ -116,24 +111,43 @@ class CarViewModel(
|
|||
initialValue = ConnectionState.DISCONNECTED
|
||||
)
|
||||
|
||||
// 添加断开连接方法
|
||||
fun disconnect() {
|
||||
(repository as BluetoothRepositoryImpl).disconnect()
|
||||
}
|
||||
|
||||
init {
|
||||
// 监听连接状态变化
|
||||
viewModelScope.launch {
|
||||
// 监听连接状态变化
|
||||
connectionState.collect { state ->
|
||||
if (state == ConnectionState.DISCONNECTED) {
|
||||
when (state) {
|
||||
ConnectionState.DISCONNECTED -> {
|
||||
// 断开连接时清空设备信息
|
||||
_connectionInfoState.value = ConnectionInfoState()
|
||||
}
|
||||
else -> {
|
||||
// 其他状态处理...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
repository.deviceName.combine(repository.deviceAddress) { name, address ->
|
||||
Pair(name, address)
|
||||
}.collect { (name, address) ->
|
||||
if (name != null && address != null) {
|
||||
updateDeviceInfo(name, address)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新设备信息的方法
|
||||
@SuppressLint("MissingPermission")
|
||||
fun updateDeviceInfo(device: BluetoothDevice) {
|
||||
private fun updateDeviceInfo(deviceName: String?, deviceAddress: String) {
|
||||
_connectionInfoState.value = ConnectionInfoState(
|
||||
name = device.name ?: "未知设备",
|
||||
address = device.address,
|
||||
name = deviceName ?: "未知设备 (${deviceAddress})",
|
||||
address = deviceAddress,
|
||||
version = "001"
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue