|
@@ -6,41 +6,101 @@ import android.content.Intent
|
|
|
import android.os.Binder
|
|
|
import android.os.IBinder
|
|
|
import android.util.ArraySet
|
|
|
+import android.util.Log
|
|
|
import androidx.bluetooth.BluetoothDevice
|
|
|
import androidx.bluetooth.BluetoothLe
|
|
|
import androidx.bluetooth.ScanFilter
|
|
|
import androidx.bluetooth.ScanResult
|
|
|
+import com.luojigou.xiaodou.ble.XDBLEConnectStatus
|
|
|
+import com.luojigou.xiaodou.ble.XDBLEUtils
|
|
|
import com.luojigou.xiaodou.ble.XDScanBLEDevice
|
|
|
+import com.luojigou.xiaodou.ble.XDScanBLEStatus
|
|
|
+import kotlinx.coroutines.CoroutineScope
|
|
|
+import kotlinx.coroutines.Dispatchers
|
|
|
+import kotlinx.coroutines.SupervisorJob
|
|
|
+import kotlinx.coroutines.currentCoroutineContext
|
|
|
import kotlinx.coroutines.flow.Flow
|
|
|
-import kotlinx.coroutines.flow.MutableSharedFlow
|
|
|
+import kotlinx.coroutines.flow.MutableStateFlow
|
|
|
+import kotlinx.coroutines.flow.launchIn
|
|
|
+import kotlinx.coroutines.flow.onCompletion
|
|
|
+import kotlinx.coroutines.flow.onEach
|
|
|
+import kotlinx.coroutines.flow.onStart
|
|
|
+import kotlinx.coroutines.withContext
|
|
|
+import java.util.UUID
|
|
|
+
|
|
|
|
|
|
@SuppressLint("MissingPermission")
|
|
|
class XDScanBLEService : Service() {
|
|
|
+ companion object {
|
|
|
+ const val ACTION_START_SCAN = "com.luojigou.xiaodou.ble.ACTION_START_SCAN"
|
|
|
+ const val ACTION_STOP_SCAN = "com.luojigou.xiaodou.ble.ACTION_STOP_SCAN"
|
|
|
+
|
|
|
+ const val ACTION_CONNECT_WIFI = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI"
|
|
|
+ const val ACTION_CONNECT_WIFI_RESULT = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT"
|
|
|
+ const val ACTION_CONNECT_WIFI_RESULT_DATA = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_DATA"
|
|
|
+ const val ACTION_CONNECT_WIFI_RESULT_ERROR = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_ERROR"
|
|
|
+ const val ACTION_CONNECT_WIFI_RESULT_SUCCESS = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_SUCCESS"
|
|
|
+ const val ACTION_CONNECT_WIFI_RESULT_FAILED = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI_RESULT_FAILED"
|
|
|
+
|
|
|
+ private val wifiConnectServiceUUID = UUID.fromString("0000ae80-0000-1000-8000-00805f9b34fb")
|
|
|
+ private val wifiConnectWriteUUID = UUID.fromString("0000ae81-0000-1000-8000-00805f9b34fb")
|
|
|
+ private val wifiConnectNotifyUUID = UUID.fromString("0000ae82-0000-1000-8000-00805f9b34fb")
|
|
|
+ private val filter: List<ScanFilter> = listOf(ScanFilter())
|
|
|
+ }
|
|
|
+
|
|
|
private val bluetoothLe: BluetoothLe by lazy { BluetoothLe(this) }
|
|
|
|
|
|
private val deviceSet: MutableSet<XDScanBLEDevice> = ArraySet()
|
|
|
|
|
|
- private val deviceListFlow = MutableSharedFlow<List<XDScanBLEDevice>(listOf())
|
|
|
+ private val deviceListFlow = MutableStateFlow<List<XDScanBLEDevice>>(listOf())
|
|
|
+
|
|
|
+ private val connectStatus = MutableStateFlow<XDBLEConnectStatus>(XDBLEConnectStatus.Waiting)
|
|
|
+ override fun onCreate() {
|
|
|
+ super.onCreate()
|
|
|
+ }
|
|
|
+
|
|
|
override fun onBind(intent: Intent?): IBinder {
|
|
|
return XDScanBLEBinder(this)
|
|
|
}
|
|
|
|
|
|
- class XDScanBLEBinder(private val service: XDScanBLEService) : Binder() {
|
|
|
- companion object {
|
|
|
- private val filter: List<ScanFilter> = listOf(
|
|
|
- ScanFilter()
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- fun getBluetooth(): BluetoothLe = service.bluetoothLe
|
|
|
-
|
|
|
- suspend fun scanBle(): Flow<ScanResult> {
|
|
|
+ class XDScanBLEBinder(private val service: XDScanBLEService) : Binder(), XDScanBLEStatus.Manager {
|
|
|
+ override suspend fun scanBle(): Flow<ScanResult> {
|
|
|
return service.bluetoothLe.scan(filter)
|
|
|
}
|
|
|
|
|
|
- suspend fun connectGatt(device: BluetoothDevice) {
|
|
|
+ override suspend fun connectWifi(device: BluetoothDevice, ssid: String, password: String): Unit = withContext(Dispatchers.IO) {
|
|
|
+ service.connectStatus.emit(XDBLEConnectStatus.Connecting(device))
|
|
|
service.bluetoothLe.connectGatt(device) {
|
|
|
+ val connection = this
|
|
|
+
|
|
|
+ val bleService = this.getService(wifiConnectServiceUUID)
|
|
|
+ if (bleService != null) {
|
|
|
+ service.connectStatus.emit(XDBLEConnectStatus.Connected(device))
|
|
|
+
|
|
|
+ val write = bleService.getCharacteristic(wifiConnectWriteUUID)
|
|
|
+ val notify = bleService.getCharacteristic(wifiConnectNotifyUUID)
|
|
|
+
|
|
|
+ if (notify != null) {
|
|
|
+ connection
|
|
|
+ .subscribeToCharacteristic(notify)
|
|
|
+ .onStart { Log.d("XDScanBLEBinder", "subscribeToCharacteristic: ") }
|
|
|
+ .onEach { XDBLEUtils.parseConnectResponse(it) }
|
|
|
+ .onCompletion { Log.d("XDScanBLEBinder", "onCompletion: ") }
|
|
|
+ .launchIn(CoroutineScope(currentCoroutineContext()))
|
|
|
+ }
|
|
|
|
|
|
+ if (write != null) {
|
|
|
+ val request = XDBLEUtils.convertToConnectRequest(ssid, password)
|
|
|
+ val result = connection.writeCharacteristic(write, request)
|
|
|
+ if (result.isSuccess) {
|
|
|
+ Log.d("XDScanBLEBinder", "connectWifi: success")
|
|
|
+ } else {
|
|
|
+ Log.d("XDScanBLEBinder", "connectWifi: failed")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ service.connectStatus.emit(XDBLEConnectStatus.Failed(device, "蓝牙无服务"))
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|