|
@@ -7,6 +7,7 @@ import android.bluetooth.BluetoothDevice
|
|
|
import android.bluetooth.BluetoothGatt
|
|
|
import android.bluetooth.BluetoothGattCallback
|
|
|
import android.bluetooth.BluetoothGattCharacteristic
|
|
|
+import android.bluetooth.BluetoothGattDescriptor
|
|
|
import android.bluetooth.BluetoothManager
|
|
|
import android.bluetooth.BluetoothProfile
|
|
|
import android.bluetooth.le.ScanCallback
|
|
@@ -46,14 +47,18 @@ class XDScanBLEService : Service() {
|
|
|
const val ACTION_SELECT_WIFI_DEVICE = "com.luojigou.xiaodou.ble.ACTION_SELECT_WIFI_DEVICE"
|
|
|
const val ACTION_SELECT_WIFI_DEVICE_DATA = "com.luojigou.xiaodou.ble.ACTION_SELECT_WIFI_DEVICE_DATA"
|
|
|
|
|
|
+ const val ACTION_CONNECT_BLE = "com.luojigou.xiaodou.ble.ACTION_CONNECT_BLE"
|
|
|
+ const val ACTION_CONNECT_BLE_RESULT_ERROR = "com.luojigou.xiaodou.ble.ACTION_CONNECT_BLE_RESULT_ERROR"
|
|
|
+ const val ACTION_CONNECT_BLE_RESULT_SUCCESS = "com.luojigou.xiaodou.ble.ACTION_CONNECT_BLE_RESULT_SUCCESS"
|
|
|
+
|
|
|
const val ACTION_CONNECT_WIFI = "com.luojigou.xiaodou.ble.ACTION_CONNECT_WIFI"
|
|
|
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 wifiConnectNotifyDescUUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
|
|
|
|
|
|
private val bleChannelName = "BLE-CHANNEL"
|
|
|
}
|
|
@@ -64,11 +69,9 @@ class XDScanBLEService : Service() {
|
|
|
|
|
|
private lateinit var bluetoothAdapter: BluetoothAdapter
|
|
|
|
|
|
- /// 选择要连接的蓝牙设备
|
|
|
- private var selectBluetoothDevice: XDScanBLEDevice? = null
|
|
|
+ private var bluetoothGatt: BluetoothGatt? = null
|
|
|
|
|
|
- /// 选择要连接的wifi网络
|
|
|
- private var selectWifiInfo: XDScanWifiInfo? = null
|
|
|
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
|
|
|
|
|
|
private var bluetoothReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
|
|
override fun onReceive(context: Context?, intent: Intent) {
|
|
@@ -78,17 +81,6 @@ class XDScanBLEService : Service() {
|
|
|
startScan()
|
|
|
}
|
|
|
|
|
|
- ACTION_CONNECT_WIFI -> {
|
|
|
- val device = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
|
- intent.getParcelableExtra("device", XDScanBLEDevice::class.java)
|
|
|
- } else {
|
|
|
- intent.getParcelableExtra<XDScanBLEDevice>("device")
|
|
|
- }
|
|
|
- val ssid = intent.getStringExtra("ssid")
|
|
|
- val password = intent.getStringExtra("password")
|
|
|
- connectWifi(device!!, ssid!!, password!!)
|
|
|
- }
|
|
|
-
|
|
|
ACTION_SELECT_BLE_DEVICE -> {
|
|
|
val bleDevice = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
|
intent.getParcelableExtra(
|
|
@@ -98,10 +90,7 @@ class XDScanBLEService : Service() {
|
|
|
intent.getParcelableExtra<XDScanBLEDevice>(ACTION_SELECT_BLE_DEVICE)
|
|
|
}
|
|
|
|
|
|
- if (bleDevice != null) {
|
|
|
- selectBluetoothDevice = bleDevice
|
|
|
- selectWifiInfo = null
|
|
|
- }
|
|
|
+ bleDevice?.let { connectBLE(it) }
|
|
|
}
|
|
|
|
|
|
ACTION_SELECT_WIFI_DEVICE -> {
|
|
@@ -113,12 +102,7 @@ class XDScanBLEService : Service() {
|
|
|
intent.getParcelableExtra<XDScanWifiInfo>(ACTION_SELECT_WIFI_DEVICE)
|
|
|
}
|
|
|
|
|
|
- if (wifiInfo != null) {
|
|
|
- selectWifiInfo = wifiInfo
|
|
|
- if (selectBluetoothDevice != null) {
|
|
|
- connectWifi(selectBluetoothDevice!!, wifiInfo.ssid, wifiInfo.password)
|
|
|
- }
|
|
|
- }
|
|
|
+ wifiInfo?.let { connectWifi(wifiInfo) }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -231,6 +215,11 @@ class XDScanBLEService : Service() {
|
|
|
}
|
|
|
|
|
|
private fun startScan() {
|
|
|
+ bluetoothGatt?.disconnect()
|
|
|
+ bluetoothGatt?.close()
|
|
|
+
|
|
|
+ writeCharacteristic = null
|
|
|
+
|
|
|
if (!bleScanning) {
|
|
|
bleScanning = true
|
|
|
bluetoothAdapter.bluetoothLeScanner.startScan(
|
|
@@ -242,13 +231,13 @@ class XDScanBLEService : Service() {
|
|
|
|
|
|
private fun delayClose() {
|
|
|
thread {
|
|
|
- sendBroadcast(Intent(ACTION_START_SCAN))
|
|
|
- Thread.sleep(5000)
|
|
|
+ broadcastUpdate(ACTION_START_SCAN)
|
|
|
+ Thread.sleep(3000)
|
|
|
if (bleScanning) {
|
|
|
stopScan()
|
|
|
}
|
|
|
- Thread.sleep(3000)
|
|
|
- sendBroadcast(Intent(ACTION_STOP_SCAN))
|
|
|
+ Thread.sleep(1000)
|
|
|
+ broadcastUpdate(ACTION_STOP_SCAN)
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -267,60 +256,134 @@ class XDScanBLEService : Service() {
|
|
|
sendBroadcast(intent)
|
|
|
}
|
|
|
|
|
|
- private fun connectWifi(device: XDScanBLEDevice, ssid: String, password: String) {
|
|
|
+ private fun connectBLE(device: XDScanBLEDevice) {
|
|
|
+ broadcastUpdate(ACTION_CONNECT_BLE)
|
|
|
val bleDevice = bluetoothDevices[device] ?: return
|
|
|
|
|
|
- val gattCallback = object : BluetoothGattCallback() {
|
|
|
- override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
|
|
- super.onConnectionStateChange(gatt, status, newState)
|
|
|
- Log.d("XDScanBLEGattCallback", "onConnectionStateChange: $status,$newState")
|
|
|
- when (newState) {
|
|
|
- BluetoothProfile.STATE_CONNECTED -> {
|
|
|
- gatt.discoverServices()
|
|
|
- }
|
|
|
+ bluetoothGatt = bleDevice.connectGatt(
|
|
|
+ this,
|
|
|
+ false,
|
|
|
+ bluetoothGattCallback,
|
|
|
+ BluetoothDevice.TRANSPORT_LE,
|
|
|
+ )
|
|
|
+ }
|
|
|
|
|
|
- BluetoothProfile.STATE_DISCONNECTED -> {
|
|
|
- gatt.close()
|
|
|
- }
|
|
|
+ private fun connectWifi(device: XDScanWifiInfo) {
|
|
|
+ if (bluetoothGatt == null || writeCharacteristic == null) return
|
|
|
+
|
|
|
+ bluetoothGatt!!.writeCharacteristic(
|
|
|
+ writeCharacteristic!!,
|
|
|
+ XDBLEUtils.convertToConnectRequest(device.ssid, device.password),
|
|
|
+ BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE,
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDestroy() {
|
|
|
+ bluetoothGatt?.disconnect()
|
|
|
+ bluetoothGatt?.close()
|
|
|
+
|
|
|
+ unregisterReceiver(bluetoothReceiver)
|
|
|
+ stopScan()
|
|
|
+ super.onDestroy()
|
|
|
+ Log.d("XDScanBLEService", "onDestroy: service destroyed")
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun broadcastUpdate(action: String) {
|
|
|
+ val intent = Intent(action)
|
|
|
+ sendBroadcast(intent)
|
|
|
+ }
|
|
|
+
|
|
|
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
|
|
|
+ override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
|
|
+ super.onConnectionStateChange(gatt, status, newState)
|
|
|
+ Log.d("XDScanBLEGattCallback", "onConnectionStateChange: $status,$newState")
|
|
|
+ when (newState) {
|
|
|
+ BluetoothProfile.STATE_CONNECTED -> {
|
|
|
+ gatt.discoverServices()
|
|
|
+ }
|
|
|
+
|
|
|
+ BluetoothProfile.STATE_DISCONNECTED -> {
|
|
|
+ gatt.close()
|
|
|
+ bluetoothGatt = null
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
|
|
- super.onServicesDiscovered(gatt, status)
|
|
|
- Log.d("XDScanBLEGattCallback", "onServicesDiscovered: $status")
|
|
|
+ override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
|
|
+ super.onServicesDiscovered(gatt, status)
|
|
|
+ Log.d("XDScanBLEGattCallback", "onServicesDiscovered: $status")
|
|
|
|
|
|
- when (status) {
|
|
|
- BluetoothGatt.GATT_SUCCESS -> {
|
|
|
- val service = gatt.getService(wifiConnectServiceUUID)!!
|
|
|
+ when (status) {
|
|
|
+ BluetoothGatt.GATT_SUCCESS -> {
|
|
|
+ val service = gatt.getService(wifiConnectServiceUUID)!!
|
|
|
|
|
|
- val notifyCharacteristic = service.getCharacteristic(wifiConnectNotifyUUID)!!
|
|
|
- val writeCharacteristic = service.getCharacteristic(wifiConnectWriteUUID)!!
|
|
|
+ val notifyCharacteristic = service.getCharacteristic(wifiConnectNotifyUUID)
|
|
|
+ writeCharacteristic = service.getCharacteristic(wifiConnectWriteUUID)
|
|
|
|
|
|
- gatt.setCharacteristicNotification(notifyCharacteristic, true)
|
|
|
+ if (notifyCharacteristic == null || writeCharacteristic == null) {
|
|
|
+ broadcastUpdate(ACTION_CONNECT_BLE_RESULT_ERROR)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ gatt.setCharacteristicNotification(notifyCharacteristic, true)
|
|
|
|
|
|
+ val notifyDescriptor = notifyCharacteristic.getDescriptor(
|
|
|
+ wifiConnectNotifyDescUUID
|
|
|
+ )
|
|
|
|
|
|
+ if (notifyDescriptor != null) {
|
|
|
+ notifyDescriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
|
|
|
+ gatt.writeDescriptor(notifyDescriptor)
|
|
|
}
|
|
|
+
|
|
|
+ broadcastUpdate(ACTION_CONNECT_BLE_RESULT_SUCCESS)
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- override fun onCharacteristicChanged(
|
|
|
- gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray
|
|
|
- ) {
|
|
|
- super.onCharacteristicChanged(gatt, characteristic, value)
|
|
|
- val result = XDBLEUtils.parseConnectResponse(value)
|
|
|
- Log.d("XDScanBLEService", "onCharacteristicChanged: $result")
|
|
|
- }
|
|
|
+ override fun onCharacteristicChanged(
|
|
|
+ gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic
|
|
|
+ ) {
|
|
|
+ super.onCharacteristicChanged(gatt, characteristic)
|
|
|
+ gatt.readCharacteristic(characteristic)
|
|
|
+ Log.d("XDScanBLEService", "onCharacteristicChanged1:")
|
|
|
}
|
|
|
|
|
|
- val connectGatt = bleDevice.connectGatt(
|
|
|
- this, false, gattCallback, BluetoothDevice.TRANSPORT_LE
|
|
|
- )
|
|
|
- }
|
|
|
+ override fun onCharacteristicChanged(
|
|
|
+ gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray
|
|
|
+ ) {
|
|
|
+ super.onCharacteristicChanged(gatt, characteristic, value)
|
|
|
+ val result = XDBLEUtils.parseConnectResponse(value)
|
|
|
+ Log.d("XDScanBLEService", "onCharacteristicChanged2: $result")
|
|
|
+ }
|
|
|
|
|
|
- override fun onDestroy() {
|
|
|
- unregisterReceiver(bluetoothReceiver)
|
|
|
- stopScan()
|
|
|
- super.onDestroy()
|
|
|
- Log.d("XDScanBLEService", "onDestroy: service destroyed")
|
|
|
+ override fun onCharacteristicRead(
|
|
|
+ gatt: BluetoothGatt,
|
|
|
+ characteristic: BluetoothGattCharacteristic,
|
|
|
+ value: ByteArray,
|
|
|
+ status: Int
|
|
|
+ ) {
|
|
|
+ super.onCharacteristicRead(gatt, characteristic, value, status)
|
|
|
+ val result = XDBLEUtils.parseConnectResponse(value)
|
|
|
+ Log.d("XDScanBLEService", "onCharacteristicRead: $result")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onCharacteristicWrite(
|
|
|
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
|
|
|
+ ) {
|
|
|
+ super.onCharacteristicWrite(gatt, characteristic, status)
|
|
|
+ Log.d("XDScanBLEService", "onCharacteristicWrite: $status")
|
|
|
+ if (status == BluetoothGatt.GATT_SUCCESS) {
|
|
|
+ Log.d("XDScanBLEService", "onCharacteristicWrite: success")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDescriptorRead(
|
|
|
+ gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray
|
|
|
+ ) {
|
|
|
+ super.onDescriptorRead(gatt, descriptor, status, value)
|
|
|
+ val result = XDBLEUtils.parseConnectResponse(value)
|
|
|
+ Log.d("XDScanBLEService", "onDescriptorRead: $result")
|
|
|
+ }
|
|
|
}
|
|
|
}
|