diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt b/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt deleted file mode 100644 index ae38dd1..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.Manifest -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -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.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Handler -import android.os.Message -import android.util.Log -import androidx.core.app.ActivityCompat -import com.pengxh.kt.lite.extensions.getSystemService -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.WeakReferenceHandler -import java.util.UUID - - -class BleDeviceManager(private val context: Context) : Handler.Callback { - private val kTag = "BleDeviceManager" - private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } - private var bluetoothAdapter: BluetoothAdapter - private var isConnecting = false - private lateinit var bleDiscoveryListener: OnDeviceDiscoveredListener - private lateinit var bleConnectListener: OnDeviceConnectListener - private lateinit var serviceUuid: UUID - private lateinit var bluetoothGatt: BluetoothGatt - - override fun handleMessage(msg: Message): Boolean { - return true - } - - init { - val bluetoothManager = context.getSystemService()!! - bluetoothAdapter = bluetoothManager.adapter - } - - /** - * 打开蓝牙 - */ - fun openBluetooth() { - if (!bluetoothAdapter.isEnabled) { - if (checkConnectPermission()) { - context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)) - } - } - } - - /** - * 蓝牙是否已打开 - */ - fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter.isEnabled - } - - /** - * 本地蓝牙是否处于正在扫描状态 - * @return true false - */ - fun isDiscovering(): Boolean { - return if (checkScanPermission()) { - bluetoothAdapter.isDiscovering - } else false; - } - - /** - * 开始扫描设备 - */ - fun startScanDevice(listener: OnDeviceDiscoveredListener, scanTime: Long) { - this.bleDiscoveryListener = listener - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback) - //设定最长扫描时间 - weakReferenceHandler.postDelayed(stopScanRunnable, scanTime) - } - } - - /** - * 停止扫描设备 - */ - fun stopDiscoverDevice() { - weakReferenceHandler.removeCallbacks(stopScanRunnable) - } - - @SuppressLint("MissingPermission") - private val stopScanRunnable = Runnable { - bleDiscoveryListener.onDeviceDiscoveryEnd() - //scanTime之后还没有扫描到设备,就停止扫描。 - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.stopScan(scanCallback) - } - } - - /** - * 扫描设备回调 - */ - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result?.apply { - if (checkConnectPermission()) { - if (!device.name.isNullOrBlank()) { - bleDiscoveryListener.onDeviceFound(device) - } - } - } - } - - override fun onBatchScanResults(results: List) { - - } - - override fun onScanFailed(errorCode: Int) { - Log.d(kTag, "onScanFailed: errorCode ===> $errorCode") - } - } - - /****连接蓝牙*********************************************************************/ - fun connectBleDevice( - bluetoothDevice: BluetoothDevice, serviceUuid: String, outTime: Long, - connectListener: OnDeviceConnectListener - ) { - if (isConnecting) { - Log.d(kTag, "connectBleDevice() ===> isConnecting = true") - return - } - this.serviceUuid = UUID.fromString(serviceUuid) - this.bleConnectListener = connectListener - if (checkConnectPermission()) { - Log.d(kTag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address) - try { - bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback) - bluetoothGatt.connect() - } catch (e: Exception) { - e.printStackTrace() - } - //设置连接超时时间 - weakReferenceHandler.postDelayed(connectTimeoutRunnable, outTime) - } - } - - private val bluetoothGattCallback = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - super.onConnectionStateChange(gatt, status, newState) - if (checkConnectPermission()) { - gatt?.apply { - Log.d(kTag, "连接的设备:" + this.device.name + " " + this.device.address) - isConnecting = true - //移除连接超时 - weakReferenceHandler.removeCallbacks(connectTimeoutRunnable) - when (newState) { - BluetoothGatt.STATE_CONNECTING -> { - Log.d(kTag, "正在连接...") - bleConnectListener.onConnecting(this) //正在连接回调 - } - - BluetoothGatt.STATE_CONNECTED -> { - Log.d(kTag, "连接成功") - //连接成功去发现服务 - discoverServices() - //设置发现服务超时时间 - weakReferenceHandler.postDelayed( - discoverServiceTimeoutRunnable, Constant.MAX_CONNECT_TIME - ) - bleConnectListener.onConnectSuccess(this, status) - } - - BluetoothGatt.STATE_DISCONNECTING -> { - Log.d(kTag, "正在断开...") - bleConnectListener.onDisConnecting(this) //正在断开回调 - } - - BluetoothGatt.STATE_DISCONNECTED -> { - when (status) { - 133 -> {//133连接异常,无法连接 - bleConnectListener.onConnectFailure(this, "连接异常!", status) - Log.d(kTag, "${this.device.address}连接失败") - } - - 62 -> {//62没有发现服务 异常断开 - bleConnectListener.onConnectFailure( - this, "没有发现服务,异常断开!", status - ) - } - - else -> { - //0:正常断开 - //8:因为距离远或者电池无法供电断开连接 - //34:断开 - //其他断开 - Log.d(kTag, "断开连接,status = $status") - bleConnectListener.onDisConnectSuccess(this, status) - } - } - close() - isConnecting = false - } - } - } - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - super.onServicesDiscovered(gatt, status) - isConnecting = false - //移除发现超时服务 - weakReferenceHandler.removeCallbacks(discoverServiceTimeoutRunnable) - //配置服务信息 - gatt?.apply { - if (configBleService(this, serviceUuid)) { - //成功发现服务回调 - bleConnectListener.onServiceDiscoverySuccess(this, status) - } else { - bleConnectListener.onServiceDiscoveryFailed(this, "获取服务特征异常") - } - } - - } - - //读取蓝牙设备发出来的数据回调 - override fun onCharacteristicRead( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, - status: Int - ) { - super.onCharacteristicRead(gatt, characteristic, value, status) - Log.d(kTag, "onCharacteristicRead => $status") - } - - //向蓝牙设备写入数据结果回调 - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int - ) { - super.onCharacteristicWrite(gatt, characteristic, status) - //将收到的字节数组转换成十六进制字符串 - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - bleConnectListener.onWriteSuccess(gatt, characteristic?.value) - } - - BluetoothGatt.GATT_FAILURE -> bleConnectListener.onWriteFailed(gatt, "写入失败") - - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "没有写入设备权限".show(context) - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray - ) { - super.onCharacteristicChanged(gatt, characteristic, value) - //接收数据 - Log.d(kTag, "收到数据:" + value.toList()) - bleConnectListener.onReceiveMessage(gatt, value) //接收数据回调 - } - - override fun onDescriptorRead( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray - ) { - super.onDescriptorRead(gatt, descriptor, status, value) - Log.d(kTag, "onDescriptorRead => 开启监听成功,可以读取设备") - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int - ) { - super.onDescriptorWrite(gatt, descriptor, status) - //开启监听成功,可以向设备写入命令了 - Log.d(kTag, "onDescriptorWrite => 开启监听成功,可以写入设备") - } - - override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) { - super.onReadRemoteRssi(gatt, rssi, status) - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - Log.d(kTag, "onReadRemoteRssi => RSSI值: $rssi") - bleConnectListener.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调 - } - - BluetoothGatt.GATT_FAILURE -> Log.d(kTag, "读取RSSI值失败,status: $status") - } - } - } - - @SuppressLint("MissingPermission") - private val connectTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //连接超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "连接超时", -1) - } - } - - @SuppressLint("MissingPermission") - private val discoverServiceTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //发现服务超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "发现服务超时", -1) - } - } - - private fun configBleService(gatt: BluetoothGatt, serviceUuid: UUID): Boolean { - var notifyCharacteristic: BluetoothGattCharacteristic? = null - gatt.services.forEach { service -> - Log.d(kTag, "configBleService => ${service.uuid}") - if (service.uuid == serviceUuid) { - service.characteristics.forEach { characteristic -> - val charaProp = characteristic.properties - if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - val notifyServiceUuid = service.uuid - val notifyCharacteristicUuid = characteristic.uuid - notifyCharacteristic = bluetoothGatt.getService(notifyServiceUuid) - .getCharacteristic(notifyCharacteristicUuid) - } - } - } else { - Log.d(kTag, "configBleService => 未匹配到uuid") - } - } - //打开读通知,打开的是notifyCharacteristic,不然不走onCharacteristicChanged回调 - if (checkConnectPermission()) { - bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) - //一定要重新设置 - notifyCharacteristic?.apply { - descriptors.forEach { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - bluetoothGatt.writeDescriptor(it) - } - } - //延迟2s,保证所有通知都能及时打开 - weakReferenceHandler.postDelayed({ }, 2000) - return true - } - return false - } - - fun disConnectDevice() { - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - isConnecting = false - } - } - - private fun checkConnectPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_CONNECT - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙连接权限".show(context) - false - } else { - true - } - } - - private fun checkScanPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_SCAN - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙扫描权限".show(context) - return false - } else { - true - } - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt b/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt deleted file mode 100644 index ae38dd1..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.Manifest -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -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.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Handler -import android.os.Message -import android.util.Log -import androidx.core.app.ActivityCompat -import com.pengxh.kt.lite.extensions.getSystemService -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.WeakReferenceHandler -import java.util.UUID - - -class BleDeviceManager(private val context: Context) : Handler.Callback { - private val kTag = "BleDeviceManager" - private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } - private var bluetoothAdapter: BluetoothAdapter - private var isConnecting = false - private lateinit var bleDiscoveryListener: OnDeviceDiscoveredListener - private lateinit var bleConnectListener: OnDeviceConnectListener - private lateinit var serviceUuid: UUID - private lateinit var bluetoothGatt: BluetoothGatt - - override fun handleMessage(msg: Message): Boolean { - return true - } - - init { - val bluetoothManager = context.getSystemService()!! - bluetoothAdapter = bluetoothManager.adapter - } - - /** - * 打开蓝牙 - */ - fun openBluetooth() { - if (!bluetoothAdapter.isEnabled) { - if (checkConnectPermission()) { - context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)) - } - } - } - - /** - * 蓝牙是否已打开 - */ - fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter.isEnabled - } - - /** - * 本地蓝牙是否处于正在扫描状态 - * @return true false - */ - fun isDiscovering(): Boolean { - return if (checkScanPermission()) { - bluetoothAdapter.isDiscovering - } else false; - } - - /** - * 开始扫描设备 - */ - fun startScanDevice(listener: OnDeviceDiscoveredListener, scanTime: Long) { - this.bleDiscoveryListener = listener - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback) - //设定最长扫描时间 - weakReferenceHandler.postDelayed(stopScanRunnable, scanTime) - } - } - - /** - * 停止扫描设备 - */ - fun stopDiscoverDevice() { - weakReferenceHandler.removeCallbacks(stopScanRunnable) - } - - @SuppressLint("MissingPermission") - private val stopScanRunnable = Runnable { - bleDiscoveryListener.onDeviceDiscoveryEnd() - //scanTime之后还没有扫描到设备,就停止扫描。 - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.stopScan(scanCallback) - } - } - - /** - * 扫描设备回调 - */ - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result?.apply { - if (checkConnectPermission()) { - if (!device.name.isNullOrBlank()) { - bleDiscoveryListener.onDeviceFound(device) - } - } - } - } - - override fun onBatchScanResults(results: List) { - - } - - override fun onScanFailed(errorCode: Int) { - Log.d(kTag, "onScanFailed: errorCode ===> $errorCode") - } - } - - /****连接蓝牙*********************************************************************/ - fun connectBleDevice( - bluetoothDevice: BluetoothDevice, serviceUuid: String, outTime: Long, - connectListener: OnDeviceConnectListener - ) { - if (isConnecting) { - Log.d(kTag, "connectBleDevice() ===> isConnecting = true") - return - } - this.serviceUuid = UUID.fromString(serviceUuid) - this.bleConnectListener = connectListener - if (checkConnectPermission()) { - Log.d(kTag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address) - try { - bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback) - bluetoothGatt.connect() - } catch (e: Exception) { - e.printStackTrace() - } - //设置连接超时时间 - weakReferenceHandler.postDelayed(connectTimeoutRunnable, outTime) - } - } - - private val bluetoothGattCallback = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - super.onConnectionStateChange(gatt, status, newState) - if (checkConnectPermission()) { - gatt?.apply { - Log.d(kTag, "连接的设备:" + this.device.name + " " + this.device.address) - isConnecting = true - //移除连接超时 - weakReferenceHandler.removeCallbacks(connectTimeoutRunnable) - when (newState) { - BluetoothGatt.STATE_CONNECTING -> { - Log.d(kTag, "正在连接...") - bleConnectListener.onConnecting(this) //正在连接回调 - } - - BluetoothGatt.STATE_CONNECTED -> { - Log.d(kTag, "连接成功") - //连接成功去发现服务 - discoverServices() - //设置发现服务超时时间 - weakReferenceHandler.postDelayed( - discoverServiceTimeoutRunnable, Constant.MAX_CONNECT_TIME - ) - bleConnectListener.onConnectSuccess(this, status) - } - - BluetoothGatt.STATE_DISCONNECTING -> { - Log.d(kTag, "正在断开...") - bleConnectListener.onDisConnecting(this) //正在断开回调 - } - - BluetoothGatt.STATE_DISCONNECTED -> { - when (status) { - 133 -> {//133连接异常,无法连接 - bleConnectListener.onConnectFailure(this, "连接异常!", status) - Log.d(kTag, "${this.device.address}连接失败") - } - - 62 -> {//62没有发现服务 异常断开 - bleConnectListener.onConnectFailure( - this, "没有发现服务,异常断开!", status - ) - } - - else -> { - //0:正常断开 - //8:因为距离远或者电池无法供电断开连接 - //34:断开 - //其他断开 - Log.d(kTag, "断开连接,status = $status") - bleConnectListener.onDisConnectSuccess(this, status) - } - } - close() - isConnecting = false - } - } - } - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - super.onServicesDiscovered(gatt, status) - isConnecting = false - //移除发现超时服务 - weakReferenceHandler.removeCallbacks(discoverServiceTimeoutRunnable) - //配置服务信息 - gatt?.apply { - if (configBleService(this, serviceUuid)) { - //成功发现服务回调 - bleConnectListener.onServiceDiscoverySuccess(this, status) - } else { - bleConnectListener.onServiceDiscoveryFailed(this, "获取服务特征异常") - } - } - - } - - //读取蓝牙设备发出来的数据回调 - override fun onCharacteristicRead( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, - status: Int - ) { - super.onCharacteristicRead(gatt, characteristic, value, status) - Log.d(kTag, "onCharacteristicRead => $status") - } - - //向蓝牙设备写入数据结果回调 - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int - ) { - super.onCharacteristicWrite(gatt, characteristic, status) - //将收到的字节数组转换成十六进制字符串 - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - bleConnectListener.onWriteSuccess(gatt, characteristic?.value) - } - - BluetoothGatt.GATT_FAILURE -> bleConnectListener.onWriteFailed(gatt, "写入失败") - - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "没有写入设备权限".show(context) - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray - ) { - super.onCharacteristicChanged(gatt, characteristic, value) - //接收数据 - Log.d(kTag, "收到数据:" + value.toList()) - bleConnectListener.onReceiveMessage(gatt, value) //接收数据回调 - } - - override fun onDescriptorRead( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray - ) { - super.onDescriptorRead(gatt, descriptor, status, value) - Log.d(kTag, "onDescriptorRead => 开启监听成功,可以读取设备") - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int - ) { - super.onDescriptorWrite(gatt, descriptor, status) - //开启监听成功,可以向设备写入命令了 - Log.d(kTag, "onDescriptorWrite => 开启监听成功,可以写入设备") - } - - override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) { - super.onReadRemoteRssi(gatt, rssi, status) - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - Log.d(kTag, "onReadRemoteRssi => RSSI值: $rssi") - bleConnectListener.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调 - } - - BluetoothGatt.GATT_FAILURE -> Log.d(kTag, "读取RSSI值失败,status: $status") - } - } - } - - @SuppressLint("MissingPermission") - private val connectTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //连接超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "连接超时", -1) - } - } - - @SuppressLint("MissingPermission") - private val discoverServiceTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //发现服务超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "发现服务超时", -1) - } - } - - private fun configBleService(gatt: BluetoothGatt, serviceUuid: UUID): Boolean { - var notifyCharacteristic: BluetoothGattCharacteristic? = null - gatt.services.forEach { service -> - Log.d(kTag, "configBleService => ${service.uuid}") - if (service.uuid == serviceUuid) { - service.characteristics.forEach { characteristic -> - val charaProp = characteristic.properties - if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - val notifyServiceUuid = service.uuid - val notifyCharacteristicUuid = characteristic.uuid - notifyCharacteristic = bluetoothGatt.getService(notifyServiceUuid) - .getCharacteristic(notifyCharacteristicUuid) - } - } - } else { - Log.d(kTag, "configBleService => 未匹配到uuid") - } - } - //打开读通知,打开的是notifyCharacteristic,不然不走onCharacteristicChanged回调 - if (checkConnectPermission()) { - bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) - //一定要重新设置 - notifyCharacteristic?.apply { - descriptors.forEach { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - bluetoothGatt.writeDescriptor(it) - } - } - //延迟2s,保证所有通知都能及时打开 - weakReferenceHandler.postDelayed({ }, 2000) - return true - } - return false - } - - fun disConnectDevice() { - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - isConnecting = false - } - } - - private fun checkConnectPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_CONNECT - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙连接权限".show(context) - false - } else { - true - } - } - - private fun checkScanPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_SCAN - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙扫描权限".show(context) - return false - } else { - true - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt deleted file mode 100644 index 53c6fc6..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothGatt - -interface OnDeviceConnectListener { - fun onConnecting(bluetoothGatt: BluetoothGatt?) //正在连接 - - fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) //连接成功 - - fun onConnectFailure(bluetoothGatt: BluetoothGatt?, exception: String, status: Int) //连接失败 - - fun onDisConnecting(bluetoothGatt: BluetoothGatt?) //正在断开 - - fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) // 断开连接 - - fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) //发现服务成功 - - fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) //发现服务失败 - - fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) //收到消息 - - fun onReceiveError(errorMsg: String) //接收数据出错 - - fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) //写入成功 - - fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) //写入失败 - - fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) //成功读取到连接信号强度 -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt b/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt deleted file mode 100644 index ae38dd1..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.Manifest -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -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.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Handler -import android.os.Message -import android.util.Log -import androidx.core.app.ActivityCompat -import com.pengxh.kt.lite.extensions.getSystemService -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.WeakReferenceHandler -import java.util.UUID - - -class BleDeviceManager(private val context: Context) : Handler.Callback { - private val kTag = "BleDeviceManager" - private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } - private var bluetoothAdapter: BluetoothAdapter - private var isConnecting = false - private lateinit var bleDiscoveryListener: OnDeviceDiscoveredListener - private lateinit var bleConnectListener: OnDeviceConnectListener - private lateinit var serviceUuid: UUID - private lateinit var bluetoothGatt: BluetoothGatt - - override fun handleMessage(msg: Message): Boolean { - return true - } - - init { - val bluetoothManager = context.getSystemService()!! - bluetoothAdapter = bluetoothManager.adapter - } - - /** - * 打开蓝牙 - */ - fun openBluetooth() { - if (!bluetoothAdapter.isEnabled) { - if (checkConnectPermission()) { - context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)) - } - } - } - - /** - * 蓝牙是否已打开 - */ - fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter.isEnabled - } - - /** - * 本地蓝牙是否处于正在扫描状态 - * @return true false - */ - fun isDiscovering(): Boolean { - return if (checkScanPermission()) { - bluetoothAdapter.isDiscovering - } else false; - } - - /** - * 开始扫描设备 - */ - fun startScanDevice(listener: OnDeviceDiscoveredListener, scanTime: Long) { - this.bleDiscoveryListener = listener - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback) - //设定最长扫描时间 - weakReferenceHandler.postDelayed(stopScanRunnable, scanTime) - } - } - - /** - * 停止扫描设备 - */ - fun stopDiscoverDevice() { - weakReferenceHandler.removeCallbacks(stopScanRunnable) - } - - @SuppressLint("MissingPermission") - private val stopScanRunnable = Runnable { - bleDiscoveryListener.onDeviceDiscoveryEnd() - //scanTime之后还没有扫描到设备,就停止扫描。 - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.stopScan(scanCallback) - } - } - - /** - * 扫描设备回调 - */ - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result?.apply { - if (checkConnectPermission()) { - if (!device.name.isNullOrBlank()) { - bleDiscoveryListener.onDeviceFound(device) - } - } - } - } - - override fun onBatchScanResults(results: List) { - - } - - override fun onScanFailed(errorCode: Int) { - Log.d(kTag, "onScanFailed: errorCode ===> $errorCode") - } - } - - /****连接蓝牙*********************************************************************/ - fun connectBleDevice( - bluetoothDevice: BluetoothDevice, serviceUuid: String, outTime: Long, - connectListener: OnDeviceConnectListener - ) { - if (isConnecting) { - Log.d(kTag, "connectBleDevice() ===> isConnecting = true") - return - } - this.serviceUuid = UUID.fromString(serviceUuid) - this.bleConnectListener = connectListener - if (checkConnectPermission()) { - Log.d(kTag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address) - try { - bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback) - bluetoothGatt.connect() - } catch (e: Exception) { - e.printStackTrace() - } - //设置连接超时时间 - weakReferenceHandler.postDelayed(connectTimeoutRunnable, outTime) - } - } - - private val bluetoothGattCallback = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - super.onConnectionStateChange(gatt, status, newState) - if (checkConnectPermission()) { - gatt?.apply { - Log.d(kTag, "连接的设备:" + this.device.name + " " + this.device.address) - isConnecting = true - //移除连接超时 - weakReferenceHandler.removeCallbacks(connectTimeoutRunnable) - when (newState) { - BluetoothGatt.STATE_CONNECTING -> { - Log.d(kTag, "正在连接...") - bleConnectListener.onConnecting(this) //正在连接回调 - } - - BluetoothGatt.STATE_CONNECTED -> { - Log.d(kTag, "连接成功") - //连接成功去发现服务 - discoverServices() - //设置发现服务超时时间 - weakReferenceHandler.postDelayed( - discoverServiceTimeoutRunnable, Constant.MAX_CONNECT_TIME - ) - bleConnectListener.onConnectSuccess(this, status) - } - - BluetoothGatt.STATE_DISCONNECTING -> { - Log.d(kTag, "正在断开...") - bleConnectListener.onDisConnecting(this) //正在断开回调 - } - - BluetoothGatt.STATE_DISCONNECTED -> { - when (status) { - 133 -> {//133连接异常,无法连接 - bleConnectListener.onConnectFailure(this, "连接异常!", status) - Log.d(kTag, "${this.device.address}连接失败") - } - - 62 -> {//62没有发现服务 异常断开 - bleConnectListener.onConnectFailure( - this, "没有发现服务,异常断开!", status - ) - } - - else -> { - //0:正常断开 - //8:因为距离远或者电池无法供电断开连接 - //34:断开 - //其他断开 - Log.d(kTag, "断开连接,status = $status") - bleConnectListener.onDisConnectSuccess(this, status) - } - } - close() - isConnecting = false - } - } - } - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - super.onServicesDiscovered(gatt, status) - isConnecting = false - //移除发现超时服务 - weakReferenceHandler.removeCallbacks(discoverServiceTimeoutRunnable) - //配置服务信息 - gatt?.apply { - if (configBleService(this, serviceUuid)) { - //成功发现服务回调 - bleConnectListener.onServiceDiscoverySuccess(this, status) - } else { - bleConnectListener.onServiceDiscoveryFailed(this, "获取服务特征异常") - } - } - - } - - //读取蓝牙设备发出来的数据回调 - override fun onCharacteristicRead( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, - status: Int - ) { - super.onCharacteristicRead(gatt, characteristic, value, status) - Log.d(kTag, "onCharacteristicRead => $status") - } - - //向蓝牙设备写入数据结果回调 - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int - ) { - super.onCharacteristicWrite(gatt, characteristic, status) - //将收到的字节数组转换成十六进制字符串 - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - bleConnectListener.onWriteSuccess(gatt, characteristic?.value) - } - - BluetoothGatt.GATT_FAILURE -> bleConnectListener.onWriteFailed(gatt, "写入失败") - - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "没有写入设备权限".show(context) - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray - ) { - super.onCharacteristicChanged(gatt, characteristic, value) - //接收数据 - Log.d(kTag, "收到数据:" + value.toList()) - bleConnectListener.onReceiveMessage(gatt, value) //接收数据回调 - } - - override fun onDescriptorRead( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray - ) { - super.onDescriptorRead(gatt, descriptor, status, value) - Log.d(kTag, "onDescriptorRead => 开启监听成功,可以读取设备") - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int - ) { - super.onDescriptorWrite(gatt, descriptor, status) - //开启监听成功,可以向设备写入命令了 - Log.d(kTag, "onDescriptorWrite => 开启监听成功,可以写入设备") - } - - override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) { - super.onReadRemoteRssi(gatt, rssi, status) - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - Log.d(kTag, "onReadRemoteRssi => RSSI值: $rssi") - bleConnectListener.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调 - } - - BluetoothGatt.GATT_FAILURE -> Log.d(kTag, "读取RSSI值失败,status: $status") - } - } - } - - @SuppressLint("MissingPermission") - private val connectTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //连接超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "连接超时", -1) - } - } - - @SuppressLint("MissingPermission") - private val discoverServiceTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //发现服务超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "发现服务超时", -1) - } - } - - private fun configBleService(gatt: BluetoothGatt, serviceUuid: UUID): Boolean { - var notifyCharacteristic: BluetoothGattCharacteristic? = null - gatt.services.forEach { service -> - Log.d(kTag, "configBleService => ${service.uuid}") - if (service.uuid == serviceUuid) { - service.characteristics.forEach { characteristic -> - val charaProp = characteristic.properties - if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - val notifyServiceUuid = service.uuid - val notifyCharacteristicUuid = characteristic.uuid - notifyCharacteristic = bluetoothGatt.getService(notifyServiceUuid) - .getCharacteristic(notifyCharacteristicUuid) - } - } - } else { - Log.d(kTag, "configBleService => 未匹配到uuid") - } - } - //打开读通知,打开的是notifyCharacteristic,不然不走onCharacteristicChanged回调 - if (checkConnectPermission()) { - bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) - //一定要重新设置 - notifyCharacteristic?.apply { - descriptors.forEach { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - bluetoothGatt.writeDescriptor(it) - } - } - //延迟2s,保证所有通知都能及时打开 - weakReferenceHandler.postDelayed({ }, 2000) - return true - } - return false - } - - fun disConnectDevice() { - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - isConnecting = false - } - } - - private fun checkConnectPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_CONNECT - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙连接权限".show(context) - false - } else { - true - } - } - - private fun checkScanPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_SCAN - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙扫描权限".show(context) - return false - } else { - true - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt deleted file mode 100644 index 53c6fc6..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothGatt - -interface OnDeviceConnectListener { - fun onConnecting(bluetoothGatt: BluetoothGatt?) //正在连接 - - fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) //连接成功 - - fun onConnectFailure(bluetoothGatt: BluetoothGatt?, exception: String, status: Int) //连接失败 - - fun onDisConnecting(bluetoothGatt: BluetoothGatt?) //正在断开 - - fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) // 断开连接 - - fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) //发现服务成功 - - fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) //发现服务失败 - - fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) //收到消息 - - fun onReceiveError(errorMsg: String) //接收数据出错 - - fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) //写入成功 - - fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) //写入失败 - - fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) //成功读取到连接信号强度 -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt deleted file mode 100644 index b49e96f..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothDevice - -interface OnDeviceDiscoveredListener { - fun onDeviceFound(device: BluetoothDevice) //搜索到设备 - - fun onDeviceDiscoveryEnd() //扫描结束 -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt b/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt deleted file mode 100644 index ae38dd1..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.Manifest -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -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.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Handler -import android.os.Message -import android.util.Log -import androidx.core.app.ActivityCompat -import com.pengxh.kt.lite.extensions.getSystemService -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.WeakReferenceHandler -import java.util.UUID - - -class BleDeviceManager(private val context: Context) : Handler.Callback { - private val kTag = "BleDeviceManager" - private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } - private var bluetoothAdapter: BluetoothAdapter - private var isConnecting = false - private lateinit var bleDiscoveryListener: OnDeviceDiscoveredListener - private lateinit var bleConnectListener: OnDeviceConnectListener - private lateinit var serviceUuid: UUID - private lateinit var bluetoothGatt: BluetoothGatt - - override fun handleMessage(msg: Message): Boolean { - return true - } - - init { - val bluetoothManager = context.getSystemService()!! - bluetoothAdapter = bluetoothManager.adapter - } - - /** - * 打开蓝牙 - */ - fun openBluetooth() { - if (!bluetoothAdapter.isEnabled) { - if (checkConnectPermission()) { - context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)) - } - } - } - - /** - * 蓝牙是否已打开 - */ - fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter.isEnabled - } - - /** - * 本地蓝牙是否处于正在扫描状态 - * @return true false - */ - fun isDiscovering(): Boolean { - return if (checkScanPermission()) { - bluetoothAdapter.isDiscovering - } else false; - } - - /** - * 开始扫描设备 - */ - fun startScanDevice(listener: OnDeviceDiscoveredListener, scanTime: Long) { - this.bleDiscoveryListener = listener - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback) - //设定最长扫描时间 - weakReferenceHandler.postDelayed(stopScanRunnable, scanTime) - } - } - - /** - * 停止扫描设备 - */ - fun stopDiscoverDevice() { - weakReferenceHandler.removeCallbacks(stopScanRunnable) - } - - @SuppressLint("MissingPermission") - private val stopScanRunnable = Runnable { - bleDiscoveryListener.onDeviceDiscoveryEnd() - //scanTime之后还没有扫描到设备,就停止扫描。 - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.stopScan(scanCallback) - } - } - - /** - * 扫描设备回调 - */ - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result?.apply { - if (checkConnectPermission()) { - if (!device.name.isNullOrBlank()) { - bleDiscoveryListener.onDeviceFound(device) - } - } - } - } - - override fun onBatchScanResults(results: List) { - - } - - override fun onScanFailed(errorCode: Int) { - Log.d(kTag, "onScanFailed: errorCode ===> $errorCode") - } - } - - /****连接蓝牙*********************************************************************/ - fun connectBleDevice( - bluetoothDevice: BluetoothDevice, serviceUuid: String, outTime: Long, - connectListener: OnDeviceConnectListener - ) { - if (isConnecting) { - Log.d(kTag, "connectBleDevice() ===> isConnecting = true") - return - } - this.serviceUuid = UUID.fromString(serviceUuid) - this.bleConnectListener = connectListener - if (checkConnectPermission()) { - Log.d(kTag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address) - try { - bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback) - bluetoothGatt.connect() - } catch (e: Exception) { - e.printStackTrace() - } - //设置连接超时时间 - weakReferenceHandler.postDelayed(connectTimeoutRunnable, outTime) - } - } - - private val bluetoothGattCallback = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - super.onConnectionStateChange(gatt, status, newState) - if (checkConnectPermission()) { - gatt?.apply { - Log.d(kTag, "连接的设备:" + this.device.name + " " + this.device.address) - isConnecting = true - //移除连接超时 - weakReferenceHandler.removeCallbacks(connectTimeoutRunnable) - when (newState) { - BluetoothGatt.STATE_CONNECTING -> { - Log.d(kTag, "正在连接...") - bleConnectListener.onConnecting(this) //正在连接回调 - } - - BluetoothGatt.STATE_CONNECTED -> { - Log.d(kTag, "连接成功") - //连接成功去发现服务 - discoverServices() - //设置发现服务超时时间 - weakReferenceHandler.postDelayed( - discoverServiceTimeoutRunnable, Constant.MAX_CONNECT_TIME - ) - bleConnectListener.onConnectSuccess(this, status) - } - - BluetoothGatt.STATE_DISCONNECTING -> { - Log.d(kTag, "正在断开...") - bleConnectListener.onDisConnecting(this) //正在断开回调 - } - - BluetoothGatt.STATE_DISCONNECTED -> { - when (status) { - 133 -> {//133连接异常,无法连接 - bleConnectListener.onConnectFailure(this, "连接异常!", status) - Log.d(kTag, "${this.device.address}连接失败") - } - - 62 -> {//62没有发现服务 异常断开 - bleConnectListener.onConnectFailure( - this, "没有发现服务,异常断开!", status - ) - } - - else -> { - //0:正常断开 - //8:因为距离远或者电池无法供电断开连接 - //34:断开 - //其他断开 - Log.d(kTag, "断开连接,status = $status") - bleConnectListener.onDisConnectSuccess(this, status) - } - } - close() - isConnecting = false - } - } - } - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - super.onServicesDiscovered(gatt, status) - isConnecting = false - //移除发现超时服务 - weakReferenceHandler.removeCallbacks(discoverServiceTimeoutRunnable) - //配置服务信息 - gatt?.apply { - if (configBleService(this, serviceUuid)) { - //成功发现服务回调 - bleConnectListener.onServiceDiscoverySuccess(this, status) - } else { - bleConnectListener.onServiceDiscoveryFailed(this, "获取服务特征异常") - } - } - - } - - //读取蓝牙设备发出来的数据回调 - override fun onCharacteristicRead( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, - status: Int - ) { - super.onCharacteristicRead(gatt, characteristic, value, status) - Log.d(kTag, "onCharacteristicRead => $status") - } - - //向蓝牙设备写入数据结果回调 - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int - ) { - super.onCharacteristicWrite(gatt, characteristic, status) - //将收到的字节数组转换成十六进制字符串 - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - bleConnectListener.onWriteSuccess(gatt, characteristic?.value) - } - - BluetoothGatt.GATT_FAILURE -> bleConnectListener.onWriteFailed(gatt, "写入失败") - - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "没有写入设备权限".show(context) - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray - ) { - super.onCharacteristicChanged(gatt, characteristic, value) - //接收数据 - Log.d(kTag, "收到数据:" + value.toList()) - bleConnectListener.onReceiveMessage(gatt, value) //接收数据回调 - } - - override fun onDescriptorRead( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray - ) { - super.onDescriptorRead(gatt, descriptor, status, value) - Log.d(kTag, "onDescriptorRead => 开启监听成功,可以读取设备") - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int - ) { - super.onDescriptorWrite(gatt, descriptor, status) - //开启监听成功,可以向设备写入命令了 - Log.d(kTag, "onDescriptorWrite => 开启监听成功,可以写入设备") - } - - override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) { - super.onReadRemoteRssi(gatt, rssi, status) - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - Log.d(kTag, "onReadRemoteRssi => RSSI值: $rssi") - bleConnectListener.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调 - } - - BluetoothGatt.GATT_FAILURE -> Log.d(kTag, "读取RSSI值失败,status: $status") - } - } - } - - @SuppressLint("MissingPermission") - private val connectTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //连接超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "连接超时", -1) - } - } - - @SuppressLint("MissingPermission") - private val discoverServiceTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //发现服务超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "发现服务超时", -1) - } - } - - private fun configBleService(gatt: BluetoothGatt, serviceUuid: UUID): Boolean { - var notifyCharacteristic: BluetoothGattCharacteristic? = null - gatt.services.forEach { service -> - Log.d(kTag, "configBleService => ${service.uuid}") - if (service.uuid == serviceUuid) { - service.characteristics.forEach { characteristic -> - val charaProp = characteristic.properties - if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - val notifyServiceUuid = service.uuid - val notifyCharacteristicUuid = characteristic.uuid - notifyCharacteristic = bluetoothGatt.getService(notifyServiceUuid) - .getCharacteristic(notifyCharacteristicUuid) - } - } - } else { - Log.d(kTag, "configBleService => 未匹配到uuid") - } - } - //打开读通知,打开的是notifyCharacteristic,不然不走onCharacteristicChanged回调 - if (checkConnectPermission()) { - bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) - //一定要重新设置 - notifyCharacteristic?.apply { - descriptors.forEach { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - bluetoothGatt.writeDescriptor(it) - } - } - //延迟2s,保证所有通知都能及时打开 - weakReferenceHandler.postDelayed({ }, 2000) - return true - } - return false - } - - fun disConnectDevice() { - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - isConnecting = false - } - } - - private fun checkConnectPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_CONNECT - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙连接权限".show(context) - false - } else { - true - } - } - - private fun checkScanPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_SCAN - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙扫描权限".show(context) - return false - } else { - true - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt deleted file mode 100644 index 53c6fc6..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothGatt - -interface OnDeviceConnectListener { - fun onConnecting(bluetoothGatt: BluetoothGatt?) //正在连接 - - fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) //连接成功 - - fun onConnectFailure(bluetoothGatt: BluetoothGatt?, exception: String, status: Int) //连接失败 - - fun onDisConnecting(bluetoothGatt: BluetoothGatt?) //正在断开 - - fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) // 断开连接 - - fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) //发现服务成功 - - fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) //发现服务失败 - - fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) //收到消息 - - fun onReceiveError(errorMsg: String) //接收数据出错 - - fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) //写入成功 - - fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) //写入失败 - - fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) //成功读取到连接信号强度 -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt deleted file mode 100644 index b49e96f..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothDevice - -interface OnDeviceDiscoveredListener { - fun onDeviceFound(device: BluetoothDevice) //搜索到设备 - - fun onDeviceDiscoveryEnd() //扫描结束 -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/view/MainActivity.kt b/app/src/main/java/com/casic/endoscope/view/MainActivity.kt index dbf0e8b..02437ee 100644 --- a/app/src/main/java/com/casic/endoscope/view/MainActivity.kt +++ b/app/src/main/java/com/casic/endoscope/view/MainActivity.kt @@ -2,8 +2,8 @@ import android.annotation.SuppressLint import android.app.Activity -import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothGatt +import android.bluetooth.BluetoothGattService import android.content.ComponentName import android.content.Context import android.content.Intent @@ -26,6 +26,7 @@ import android.view.View import androidx.lifecycle.lifecycleScope import com.casic.endoscope.R +import com.casic.endoscope.base.BaseApplication import com.casic.endoscope.databinding.ActivityMainBinding import com.casic.endoscope.extensions.check import com.casic.endoscope.extensions.convertValue @@ -38,15 +39,18 @@ import com.casic.endoscope.utils.DataBaseManager import com.casic.endoscope.utils.FileManager import com.casic.endoscope.utils.ProjectConstant -import com.casic.endoscope.utils.ble.BleDeviceManager -import com.casic.endoscope.utils.ble.OnDeviceConnectListener -import com.casic.endoscope.utils.ble.OnDeviceDiscoveredListener import com.casic.endoscope.utils.hk.MessageCodeHub import com.casic.endoscope.utils.hk.SDKGuider import com.casic.endoscope.widgets.AlertControlDialog import com.casic.endoscope.widgets.BluetoothDeviceDialog import com.casic.endoscope.widgets.LineChartMarkerView import com.casic.endoscope.widgets.PreviewImageDialog +import com.clj.fastble.BleManager +import com.clj.fastble.callback.BleGattCallback +import com.clj.fastble.callback.BleNotifyCallback +import com.clj.fastble.callback.BleScanCallback +import com.clj.fastble.data.BleDevice +import com.clj.fastble.exception.BleException import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.data.LineData import com.github.mikephil.charting.data.LineDataSet @@ -83,6 +87,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID @SuppressLint("all") @@ -92,13 +97,12 @@ private val kTag = "MainActivity" private val context = this@MainActivity private val hkSDK by lazy { HCNetSDK.getInstance() } - private val bleDeviceManager by lazy { BleDeviceManager(this) } private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 10.dp2px(this) } private val selectedSpeed = 7 private val messageCode = 2024021901 private val requestManageFilesAccess = 2024041301 - private val bluetoothDevices = ArrayList() + private val bluetoothDevices = ArrayList() private val xAxisLabels = ArrayList() private val densityEntries = ArrayList() private val lineDataSets = ArrayList() @@ -106,7 +110,6 @@ //趋势线起点X坐标 private var i = 0 - private var isConnected = false private var clickTime = 0L private var previewHandle = -1 private var selectChannel = -1 @@ -127,6 +130,7 @@ private var timerTask: TimerTask? = null private var seconds = 0L private var screenShortService: ScreenShortRecordService? = null + private var connectedDevice: BleDevice? = null private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var dataSet: LineDataSet private lateinit var lineData: LineData @@ -165,6 +169,14 @@ } } + BleManager.getInstance().init(BaseApplication.get()) + BleManager.getInstance() + .enableLog(true) + .setReConnectCount(1, 5000) + .setSplitWriteNum(20) + .setConnectOverTime(10 * 1000L) + .setOperateTimeout(5000) + //显示数据 weakReferenceHandler = WeakReferenceHandler(this) weakReferenceHandler.sendEmptyMessage(messageCode) @@ -187,44 +199,33 @@ } binding.searchBleButton.setOnClickListener { - if (!bleDeviceManager.isBluetoothEnabled()) { - bleDeviceManager.openBluetooth() + if (!BleManager.getInstance().isBlueEnable) { + BleManager.getInstance().enableBluetooth() } - if (bleDeviceManager.isDiscovering()) { - bleDeviceManager.stopDiscoverDevice() - } - - if (isConnected) { - bleDeviceManager.disConnectDevice() + if (BleManager.getInstance().isConnected(connectedDevice)) { + BleManager.getInstance().disconnect(connectedDevice) } else { - LoadingDialogHub.show(this, "设备搜索中...") - bleDeviceManager.startScanDevice(object : OnDeviceDiscoveredListener { - override fun onDeviceFound(device: BluetoothDevice) { - if (bluetoothDevices.isEmpty()) { - bluetoothDevices.add(device) - } else { - //0表示未添加到list的新设备,1表示已经扫描并添加到list的设备 - var judge = 0 - for (temp in bluetoothDevices) { - if (temp.address == device.address) { - judge = 1 - break - } - } - if (judge == 0) { - bluetoothDevices.add(device) + BleManager.getInstance().scan(object : BleScanCallback() { + override fun onScanStarted(success: Boolean) { + LoadingDialogHub.show(this@MainActivity, "设备搜索中...") + } + + override fun onScanning(bleDevice: BleDevice) { + + } + + override fun onScanFinished(scanResultList: List) { + LoadingDialogHub.dismiss() + + scanResultList.forEach { + if (!it.name.isNullOrBlank()) { + bluetoothDevices.add(it) } } - } - - override fun onDeviceDiscoveryEnd() { - LoadingDialogHub.dismiss() - //显示搜索到设备列表 showScanResult() } - - }, 10 * 1000) + }) } } @@ -536,6 +537,12 @@ unbindService(serviceConnection) } + override fun onDestroy() { + super.onDestroy() + BleManager.getInstance().disconnect(connectedDevice) + BleManager.getInstance().destroy() + } + override fun handleMessage(msg: Message): Boolean { if (msg.what == messageCode) { //绑定数据 @@ -593,15 +600,112 @@ }).build().show() } - private fun startConnectDevice(device: BluetoothDevice) { + private fun startConnectDevice(device: BleDevice) { // 当前蓝牙设备 - if (!isConnected) { - LoadingDialogHub.show(this, "正在连接...") - bleDeviceManager.connectBleDevice( - device, ProjectConstant.SERVICE_UUID, 10 * 1000, bleConnectListener - ) + if (!BleManager.getInstance().isConnected(connectedDevice)) { + BleManager.getInstance().connect(device, object : BleGattCallback() { + override fun onStartConnect() { + LoadingDialogHub.show(this@MainActivity, "正在连接...") + } + + override fun onConnectFail(bleDevice: BleDevice, exception: BleException) { + LoadingDialogHub.dismiss() + "连接失败,请重试".show(context) + } + + override fun onConnectSuccess( + bleDevice: BleDevice, gatt: BluetoothGatt, status: Int + ) { + Log.d(kTag, "onConnectSuccess: ${bleDevice.name} 连接成功") + connectedDevice = bleDevice + notifyDeviceService(bleDevice, gatt) + } + + override fun onDisConnected( + isActiveDisConnected: Boolean, bleDevice: BleDevice, + gatt: BluetoothGatt, status: Int + ) { + Log.d(kTag, "onDisConnected => $status") + connectedDevice = null + binding.searchBleButton.text = "搜索蓝牙" + binding.stateView.text = "未连接" + binding.stateView.setTextColor(Color.RED) + } + }) } else { - bleDeviceManager.disConnectDevice() + BleManager.getInstance().disconnect(connectedDevice) + } + } + + private fun notifyDeviceService(bleDevice: BleDevice, gatt: BluetoothGatt) { + val serviceList: List = gatt.services + for (service in serviceList) { + if (service.uuid == UUID.fromString(ProjectConstant.SERVICE_UUID)) { + val characteristicList = service.characteristics + for (characteristic in characteristicList) { + val uuidCharacteristic = characteristic.uuid + BleManager.getInstance().notify( + bleDevice, service.uuid.toString(), uuidCharacteristic.toString(), + object : BleNotifyCallback() { + override fun onNotifySuccess() { + LoadingDialogHub.dismiss() + "连接成功".show(context) + binding.searchBleButton.text = "断开连接" + binding.stateView.text = "已连接" + binding.stateView.setTextColor(Color.GREEN) + } + + override fun onNotifyFailure(exception: BleException) { + LoadingDialogHub.dismiss() + "蓝牙通讯协议不支持".show(context) + connectedDevice = null + } + + override fun onCharacteristicChanged(data: ByteArray) { + // 打开通知后,设备发过来的数据 + if (data.check()) { + /***将值渲染到曲线图****************************************************************/ + lifecycleScope.launch(Dispatchers.Main) { + val currentTime = + System.currentTimeMillis().timestampToTime() + //解析返回值 + val density = data.convertValue() + withContext(Dispatchers.IO) { + //协程切换为子线程将数据保存在数据库 + DataBaseManager.get.saveGasDensity(density, currentTime) + } + //时间作为X轴 + xAxisLabels.add(currentTime) + + //浓度作为Y轴 + val entry = Entry(i++.toFloat(), density.toFloat(), "浓度") + densityEntries.add(entry) + + //转化为控件需要的Data + dataSet = LineDataSet(densityEntries, "") + dataSet.setDrawCircles(false) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + //线条颜色 + dataSet.color = Color.RED + lineDataSets.add(dataSet) + lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + + //解决折线点太多导致卡顿问题 + if (lineData.entryCount > 50) { + lineData.removeDataSet(0) + lineData.notifyDataChanged() + } + binding.lineChart.data = lineData + binding.lineChart.invalidate() + } + } else { + Log.d(kTag, "onReceiveMessage: 数据校验失败") + } + } + }) + } + } } } @@ -663,111 +767,4 @@ } return super.onKeyDown(keyCode, event) } - - /***低功耗蓝牙********************************************/ - private val bleConnectListener = object : OnDeviceConnectListener { - override fun onConnecting(bluetoothGatt: BluetoothGatt?) { - Log.d(kTag, "onConnecting => ") - } - - override fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - Log.d(kTag, "onConnectSuccess => $status") - } - - override fun onConnectFailure( - bluetoothGatt: BluetoothGatt?, exception: String, status: Int - ) { - Log.d(kTag, "onConnectFailure => $status") - isConnected = false - } - - override fun onDisConnecting(bluetoothGatt: BluetoothGatt?) { - Log.d(kTag, "onDisConnecting => ") - } - - override fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - lifecycleScope.launch(Dispatchers.Main) { - Log.d(kTag, "onDisConnectSuccess => $status") - isConnected = false - binding.searchBleButton.text = "搜索蓝牙" - binding.stateView.text = "未连接" - binding.stateView.setTextColor(Color.RED) - } - } - - override fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - lifecycleScope.launch(Dispatchers.Main) { - Log.d(kTag, "onServiceDiscoverySuccess => $status") - LoadingDialogHub.dismiss() - "连接成功".show(context) - isConnected = true - binding.searchBleButton.text = "断开连接" - binding.stateView.text = "已连接" - binding.stateView.setTextColor(Color.GREEN) - } - } - - override fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) { - Log.d(kTag, "onServiceDiscoveryFailed => ") - isConnected = false - } - - override fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) { - //[97, 97, 32, 48, 49, 32, 48, 48, 32, 48, 48, 32, 48, 48, 32, 48, 100, 32, 53, 53, 32] - if (value.check()) { - /***将值渲染到曲线图****************************************************************/ - lifecycleScope.launch(Dispatchers.Main) { - val currentTime = System.currentTimeMillis().timestampToTime() - //解析返回值 - val density = value.convertValue() - withContext(Dispatchers.IO) { - //协程切换为子线程将数据保存在数据库 - DataBaseManager.get.saveGasDensity(density, currentTime) - } - //时间作为X轴 - xAxisLabels.add(currentTime) - - //浓度作为Y轴 - val entry = Entry(i++.toFloat(), density.toFloat(), "浓度") - densityEntries.add(entry) - - //转化为控件需要的Data - dataSet = LineDataSet(densityEntries, "") - dataSet.setDrawCircles(false) - dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER - //线条颜色 - dataSet.color = Color.RED - lineDataSets.add(dataSet) - lineData = LineData(lineDataSets) - lineData.setDrawValues(false) - - //解决折线点太多导致卡顿问题 - if (lineData.entryCount > 50) { - lineData.removeDataSet(0) - lineData.notifyDataChanged() - } - binding.lineChart.data = lineData - binding.lineChart.invalidate() - } - } else { - Log.d(kTag, "onReceiveMessage: 数据校验失败") - } - } - - override fun onReceiveError(errorMsg: String) { - Log.d(kTag, "onReceiveError => $errorMsg") - } - - override fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) { - Log.d(kTag, "onWriteSuccess => ${msg.contentToString()}") - } - - override fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) { - Log.d(kTag, "onWriteFailed => $errorMsg") - } - - override fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) { - Log.d(kTag, "onReadRssi => $rssi") - } - } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 9b25206..edb87a6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -111,4 +111,6 @@ implementation 'org.greenrobot:greendao:3.3.0' //数据库升级 implementation 'io.github.yuweiguocn:GreenDaoUpgradeHelper:v2.2.1' + //蓝牙 + implementation 'com.github.Jasonchenlijian:FastBle:2.4.0' } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt index 78c2ac0..23cd66c 100644 --- a/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt +++ b/app/src/main/java/com/casic/endoscope/utils/ProjectConstant.kt @@ -53,4 +53,12 @@ const val HK_NET_PASSWORD = "casic203" const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" //连接设备的UUID +// const val SERVICE_UUID = "00001800-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a00-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a01-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002a04-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00002aa6-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "00001801-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb" +// const val SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb" } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt b/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt deleted file mode 100644 index ae38dd1..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/BleDeviceManager.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.Manifest -import android.annotation.SuppressLint -import android.bluetooth.BluetoothAdapter -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.le.ScanCallback -import android.bluetooth.le.ScanResult -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Handler -import android.os.Message -import android.util.Log -import androidx.core.app.ActivityCompat -import com.pengxh.kt.lite.extensions.getSystemService -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.WeakReferenceHandler -import java.util.UUID - - -class BleDeviceManager(private val context: Context) : Handler.Callback { - private val kTag = "BleDeviceManager" - private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } - private var bluetoothAdapter: BluetoothAdapter - private var isConnecting = false - private lateinit var bleDiscoveryListener: OnDeviceDiscoveredListener - private lateinit var bleConnectListener: OnDeviceConnectListener - private lateinit var serviceUuid: UUID - private lateinit var bluetoothGatt: BluetoothGatt - - override fun handleMessage(msg: Message): Boolean { - return true - } - - init { - val bluetoothManager = context.getSystemService()!! - bluetoothAdapter = bluetoothManager.adapter - } - - /** - * 打开蓝牙 - */ - fun openBluetooth() { - if (!bluetoothAdapter.isEnabled) { - if (checkConnectPermission()) { - context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)) - } - } - } - - /** - * 蓝牙是否已打开 - */ - fun isBluetoothEnabled(): Boolean { - return bluetoothAdapter.isEnabled - } - - /** - * 本地蓝牙是否处于正在扫描状态 - * @return true false - */ - fun isDiscovering(): Boolean { - return if (checkScanPermission()) { - bluetoothAdapter.isDiscovering - } else false; - } - - /** - * 开始扫描设备 - */ - fun startScanDevice(listener: OnDeviceDiscoveredListener, scanTime: Long) { - this.bleDiscoveryListener = listener - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.startScan(scanCallback) - //设定最长扫描时间 - weakReferenceHandler.postDelayed(stopScanRunnable, scanTime) - } - } - - /** - * 停止扫描设备 - */ - fun stopDiscoverDevice() { - weakReferenceHandler.removeCallbacks(stopScanRunnable) - } - - @SuppressLint("MissingPermission") - private val stopScanRunnable = Runnable { - bleDiscoveryListener.onDeviceDiscoveryEnd() - //scanTime之后还没有扫描到设备,就停止扫描。 - if (checkScanPermission()) { - bluetoothAdapter.bluetoothLeScanner.stopScan(scanCallback) - } - } - - /** - * 扫描设备回调 - */ - private val scanCallback = object : ScanCallback() { - override fun onScanResult(callbackType: Int, result: ScanResult?) { - result?.apply { - if (checkConnectPermission()) { - if (!device.name.isNullOrBlank()) { - bleDiscoveryListener.onDeviceFound(device) - } - } - } - } - - override fun onBatchScanResults(results: List) { - - } - - override fun onScanFailed(errorCode: Int) { - Log.d(kTag, "onScanFailed: errorCode ===> $errorCode") - } - } - - /****连接蓝牙*********************************************************************/ - fun connectBleDevice( - bluetoothDevice: BluetoothDevice, serviceUuid: String, outTime: Long, - connectListener: OnDeviceConnectListener - ) { - if (isConnecting) { - Log.d(kTag, "connectBleDevice() ===> isConnecting = true") - return - } - this.serviceUuid = UUID.fromString(serviceUuid) - this.bleConnectListener = connectListener - if (checkConnectPermission()) { - Log.d(kTag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address) - try { - bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback) - bluetoothGatt.connect() - } catch (e: Exception) { - e.printStackTrace() - } - //设置连接超时时间 - weakReferenceHandler.postDelayed(connectTimeoutRunnable, outTime) - } - } - - private val bluetoothGattCallback = object : BluetoothGattCallback() { - override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { - super.onConnectionStateChange(gatt, status, newState) - if (checkConnectPermission()) { - gatt?.apply { - Log.d(kTag, "连接的设备:" + this.device.name + " " + this.device.address) - isConnecting = true - //移除连接超时 - weakReferenceHandler.removeCallbacks(connectTimeoutRunnable) - when (newState) { - BluetoothGatt.STATE_CONNECTING -> { - Log.d(kTag, "正在连接...") - bleConnectListener.onConnecting(this) //正在连接回调 - } - - BluetoothGatt.STATE_CONNECTED -> { - Log.d(kTag, "连接成功") - //连接成功去发现服务 - discoverServices() - //设置发现服务超时时间 - weakReferenceHandler.postDelayed( - discoverServiceTimeoutRunnable, Constant.MAX_CONNECT_TIME - ) - bleConnectListener.onConnectSuccess(this, status) - } - - BluetoothGatt.STATE_DISCONNECTING -> { - Log.d(kTag, "正在断开...") - bleConnectListener.onDisConnecting(this) //正在断开回调 - } - - BluetoothGatt.STATE_DISCONNECTED -> { - when (status) { - 133 -> {//133连接异常,无法连接 - bleConnectListener.onConnectFailure(this, "连接异常!", status) - Log.d(kTag, "${this.device.address}连接失败") - } - - 62 -> {//62没有发现服务 异常断开 - bleConnectListener.onConnectFailure( - this, "没有发现服务,异常断开!", status - ) - } - - else -> { - //0:正常断开 - //8:因为距离远或者电池无法供电断开连接 - //34:断开 - //其他断开 - Log.d(kTag, "断开连接,status = $status") - bleConnectListener.onDisConnectSuccess(this, status) - } - } - close() - isConnecting = false - } - } - } - } - } - - override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { - super.onServicesDiscovered(gatt, status) - isConnecting = false - //移除发现超时服务 - weakReferenceHandler.removeCallbacks(discoverServiceTimeoutRunnable) - //配置服务信息 - gatt?.apply { - if (configBleService(this, serviceUuid)) { - //成功发现服务回调 - bleConnectListener.onServiceDiscoverySuccess(this, status) - } else { - bleConnectListener.onServiceDiscoveryFailed(this, "获取服务特征异常") - } - } - - } - - //读取蓝牙设备发出来的数据回调 - override fun onCharacteristicRead( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray, - status: Int - ) { - super.onCharacteristicRead(gatt, characteristic, value, status) - Log.d(kTag, "onCharacteristicRead => $status") - } - - //向蓝牙设备写入数据结果回调 - override fun onCharacteristicWrite( - gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int - ) { - super.onCharacteristicWrite(gatt, characteristic, status) - //将收到的字节数组转换成十六进制字符串 - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - bleConnectListener.onWriteSuccess(gatt, characteristic?.value) - } - - BluetoothGatt.GATT_FAILURE -> bleConnectListener.onWriteFailed(gatt, "写入失败") - - BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> "没有写入设备权限".show(context) - } - } - - override fun onCharacteristicChanged( - gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray - ) { - super.onCharacteristicChanged(gatt, characteristic, value) - //接收数据 - Log.d(kTag, "收到数据:" + value.toList()) - bleConnectListener.onReceiveMessage(gatt, value) //接收数据回调 - } - - override fun onDescriptorRead( - gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int, value: ByteArray - ) { - super.onDescriptorRead(gatt, descriptor, status, value) - Log.d(kTag, "onDescriptorRead => 开启监听成功,可以读取设备") - } - - override fun onDescriptorWrite( - gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int - ) { - super.onDescriptorWrite(gatt, descriptor, status) - //开启监听成功,可以向设备写入命令了 - Log.d(kTag, "onDescriptorWrite => 开启监听成功,可以写入设备") - } - - override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) { - super.onReadRemoteRssi(gatt, rssi, status) - when (status) { - BluetoothGatt.GATT_SUCCESS -> { - Log.d(kTag, "onReadRemoteRssi => RSSI值: $rssi") - bleConnectListener.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调 - } - - BluetoothGatt.GATT_FAILURE -> Log.d(kTag, "读取RSSI值失败,status: $status") - } - } - } - - @SuppressLint("MissingPermission") - private val connectTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //连接超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "连接超时", -1) - } - } - - @SuppressLint("MissingPermission") - private val discoverServiceTimeoutRunnable = Runnable { - isConnecting = false - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - //发现服务超时当作连接失败回调 - bleConnectListener.onConnectFailure(bluetoothGatt, "发现服务超时", -1) - } - } - - private fun configBleService(gatt: BluetoothGatt, serviceUuid: UUID): Boolean { - var notifyCharacteristic: BluetoothGattCharacteristic? = null - gatt.services.forEach { service -> - Log.d(kTag, "configBleService => ${service.uuid}") - if (service.uuid == serviceUuid) { - service.characteristics.forEach { characteristic -> - val charaProp = characteristic.properties - if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) { - val notifyServiceUuid = service.uuid - val notifyCharacteristicUuid = characteristic.uuid - notifyCharacteristic = bluetoothGatt.getService(notifyServiceUuid) - .getCharacteristic(notifyCharacteristicUuid) - } - } - } else { - Log.d(kTag, "configBleService => 未匹配到uuid") - } - } - //打开读通知,打开的是notifyCharacteristic,不然不走onCharacteristicChanged回调 - if (checkConnectPermission()) { - bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true) - //一定要重新设置 - notifyCharacteristic?.apply { - descriptors.forEach { - it.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - bluetoothGatt.writeDescriptor(it) - } - } - //延迟2s,保证所有通知都能及时打开 - weakReferenceHandler.postDelayed({ }, 2000) - return true - } - return false - } - - fun disConnectDevice() { - if (checkConnectPermission()) { - bluetoothGatt.disconnect() - isConnecting = false - } - } - - private fun checkConnectPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_CONNECT - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙连接权限".show(context) - false - } else { - true - } - } - - private fun checkScanPermission(): Boolean { - return if (ActivityCompat.checkSelfPermission( - context, Manifest.permission.BLUETOOTH_SCAN - ) != PackageManager.PERMISSION_GRANTED - ) { - "缺少蓝牙扫描权限".show(context) - return false - } else { - true - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt deleted file mode 100644 index 53c6fc6..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceConnectListener.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothGatt - -interface OnDeviceConnectListener { - fun onConnecting(bluetoothGatt: BluetoothGatt?) //正在连接 - - fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) //连接成功 - - fun onConnectFailure(bluetoothGatt: BluetoothGatt?, exception: String, status: Int) //连接失败 - - fun onDisConnecting(bluetoothGatt: BluetoothGatt?) //正在断开 - - fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) // 断开连接 - - fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) //发现服务成功 - - fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) //发现服务失败 - - fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) //收到消息 - - fun onReceiveError(errorMsg: String) //接收数据出错 - - fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) //写入成功 - - fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) //写入失败 - - fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) //成功读取到连接信号强度 -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt b/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt deleted file mode 100644 index b49e96f..0000000 --- a/app/src/main/java/com/casic/endoscope/utils/ble/OnDeviceDiscoveredListener.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.casic.endoscope.utils.ble - -import android.bluetooth.BluetoothDevice - -interface OnDeviceDiscoveredListener { - fun onDeviceFound(device: BluetoothDevice) //搜索到设备 - - fun onDeviceDiscoveryEnd() //扫描结束 -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/view/MainActivity.kt b/app/src/main/java/com/casic/endoscope/view/MainActivity.kt index dbf0e8b..02437ee 100644 --- a/app/src/main/java/com/casic/endoscope/view/MainActivity.kt +++ b/app/src/main/java/com/casic/endoscope/view/MainActivity.kt @@ -2,8 +2,8 @@ import android.annotation.SuppressLint import android.app.Activity -import android.bluetooth.BluetoothDevice import android.bluetooth.BluetoothGatt +import android.bluetooth.BluetoothGattService import android.content.ComponentName import android.content.Context import android.content.Intent @@ -26,6 +26,7 @@ import android.view.View import androidx.lifecycle.lifecycleScope import com.casic.endoscope.R +import com.casic.endoscope.base.BaseApplication import com.casic.endoscope.databinding.ActivityMainBinding import com.casic.endoscope.extensions.check import com.casic.endoscope.extensions.convertValue @@ -38,15 +39,18 @@ import com.casic.endoscope.utils.DataBaseManager import com.casic.endoscope.utils.FileManager import com.casic.endoscope.utils.ProjectConstant -import com.casic.endoscope.utils.ble.BleDeviceManager -import com.casic.endoscope.utils.ble.OnDeviceConnectListener -import com.casic.endoscope.utils.ble.OnDeviceDiscoveredListener import com.casic.endoscope.utils.hk.MessageCodeHub import com.casic.endoscope.utils.hk.SDKGuider import com.casic.endoscope.widgets.AlertControlDialog import com.casic.endoscope.widgets.BluetoothDeviceDialog import com.casic.endoscope.widgets.LineChartMarkerView import com.casic.endoscope.widgets.PreviewImageDialog +import com.clj.fastble.BleManager +import com.clj.fastble.callback.BleGattCallback +import com.clj.fastble.callback.BleNotifyCallback +import com.clj.fastble.callback.BleScanCallback +import com.clj.fastble.data.BleDevice +import com.clj.fastble.exception.BleException import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.data.LineData import com.github.mikephil.charting.data.LineDataSet @@ -83,6 +87,7 @@ import java.util.Locale import java.util.Timer import java.util.TimerTask +import java.util.UUID @SuppressLint("all") @@ -92,13 +97,12 @@ private val kTag = "MainActivity" private val context = this@MainActivity private val hkSDK by lazy { HCNetSDK.getInstance() } - private val bleDeviceManager by lazy { BleDeviceManager(this) } private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) } private val marginOffset by lazy { 10.dp2px(this) } private val selectedSpeed = 7 private val messageCode = 2024021901 private val requestManageFilesAccess = 2024041301 - private val bluetoothDevices = ArrayList() + private val bluetoothDevices = ArrayList() private val xAxisLabels = ArrayList() private val densityEntries = ArrayList() private val lineDataSets = ArrayList() @@ -106,7 +110,6 @@ //趋势线起点X坐标 private var i = 0 - private var isConnected = false private var clickTime = 0L private var previewHandle = -1 private var selectChannel = -1 @@ -127,6 +130,7 @@ private var timerTask: TimerTask? = null private var seconds = 0L private var screenShortService: ScreenShortRecordService? = null + private var connectedDevice: BleDevice? = null private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var dataSet: LineDataSet private lateinit var lineData: LineData @@ -165,6 +169,14 @@ } } + BleManager.getInstance().init(BaseApplication.get()) + BleManager.getInstance() + .enableLog(true) + .setReConnectCount(1, 5000) + .setSplitWriteNum(20) + .setConnectOverTime(10 * 1000L) + .setOperateTimeout(5000) + //显示数据 weakReferenceHandler = WeakReferenceHandler(this) weakReferenceHandler.sendEmptyMessage(messageCode) @@ -187,44 +199,33 @@ } binding.searchBleButton.setOnClickListener { - if (!bleDeviceManager.isBluetoothEnabled()) { - bleDeviceManager.openBluetooth() + if (!BleManager.getInstance().isBlueEnable) { + BleManager.getInstance().enableBluetooth() } - if (bleDeviceManager.isDiscovering()) { - bleDeviceManager.stopDiscoverDevice() - } - - if (isConnected) { - bleDeviceManager.disConnectDevice() + if (BleManager.getInstance().isConnected(connectedDevice)) { + BleManager.getInstance().disconnect(connectedDevice) } else { - LoadingDialogHub.show(this, "设备搜索中...") - bleDeviceManager.startScanDevice(object : OnDeviceDiscoveredListener { - override fun onDeviceFound(device: BluetoothDevice) { - if (bluetoothDevices.isEmpty()) { - bluetoothDevices.add(device) - } else { - //0表示未添加到list的新设备,1表示已经扫描并添加到list的设备 - var judge = 0 - for (temp in bluetoothDevices) { - if (temp.address == device.address) { - judge = 1 - break - } - } - if (judge == 0) { - bluetoothDevices.add(device) + BleManager.getInstance().scan(object : BleScanCallback() { + override fun onScanStarted(success: Boolean) { + LoadingDialogHub.show(this@MainActivity, "设备搜索中...") + } + + override fun onScanning(bleDevice: BleDevice) { + + } + + override fun onScanFinished(scanResultList: List) { + LoadingDialogHub.dismiss() + + scanResultList.forEach { + if (!it.name.isNullOrBlank()) { + bluetoothDevices.add(it) } } - } - - override fun onDeviceDiscoveryEnd() { - LoadingDialogHub.dismiss() - //显示搜索到设备列表 showScanResult() } - - }, 10 * 1000) + }) } } @@ -536,6 +537,12 @@ unbindService(serviceConnection) } + override fun onDestroy() { + super.onDestroy() + BleManager.getInstance().disconnect(connectedDevice) + BleManager.getInstance().destroy() + } + override fun handleMessage(msg: Message): Boolean { if (msg.what == messageCode) { //绑定数据 @@ -593,15 +600,112 @@ }).build().show() } - private fun startConnectDevice(device: BluetoothDevice) { + private fun startConnectDevice(device: BleDevice) { // 当前蓝牙设备 - if (!isConnected) { - LoadingDialogHub.show(this, "正在连接...") - bleDeviceManager.connectBleDevice( - device, ProjectConstant.SERVICE_UUID, 10 * 1000, bleConnectListener - ) + if (!BleManager.getInstance().isConnected(connectedDevice)) { + BleManager.getInstance().connect(device, object : BleGattCallback() { + override fun onStartConnect() { + LoadingDialogHub.show(this@MainActivity, "正在连接...") + } + + override fun onConnectFail(bleDevice: BleDevice, exception: BleException) { + LoadingDialogHub.dismiss() + "连接失败,请重试".show(context) + } + + override fun onConnectSuccess( + bleDevice: BleDevice, gatt: BluetoothGatt, status: Int + ) { + Log.d(kTag, "onConnectSuccess: ${bleDevice.name} 连接成功") + connectedDevice = bleDevice + notifyDeviceService(bleDevice, gatt) + } + + override fun onDisConnected( + isActiveDisConnected: Boolean, bleDevice: BleDevice, + gatt: BluetoothGatt, status: Int + ) { + Log.d(kTag, "onDisConnected => $status") + connectedDevice = null + binding.searchBleButton.text = "搜索蓝牙" + binding.stateView.text = "未连接" + binding.stateView.setTextColor(Color.RED) + } + }) } else { - bleDeviceManager.disConnectDevice() + BleManager.getInstance().disconnect(connectedDevice) + } + } + + private fun notifyDeviceService(bleDevice: BleDevice, gatt: BluetoothGatt) { + val serviceList: List = gatt.services + for (service in serviceList) { + if (service.uuid == UUID.fromString(ProjectConstant.SERVICE_UUID)) { + val characteristicList = service.characteristics + for (characteristic in characteristicList) { + val uuidCharacteristic = characteristic.uuid + BleManager.getInstance().notify( + bleDevice, service.uuid.toString(), uuidCharacteristic.toString(), + object : BleNotifyCallback() { + override fun onNotifySuccess() { + LoadingDialogHub.dismiss() + "连接成功".show(context) + binding.searchBleButton.text = "断开连接" + binding.stateView.text = "已连接" + binding.stateView.setTextColor(Color.GREEN) + } + + override fun onNotifyFailure(exception: BleException) { + LoadingDialogHub.dismiss() + "蓝牙通讯协议不支持".show(context) + connectedDevice = null + } + + override fun onCharacteristicChanged(data: ByteArray) { + // 打开通知后,设备发过来的数据 + if (data.check()) { + /***将值渲染到曲线图****************************************************************/ + lifecycleScope.launch(Dispatchers.Main) { + val currentTime = + System.currentTimeMillis().timestampToTime() + //解析返回值 + val density = data.convertValue() + withContext(Dispatchers.IO) { + //协程切换为子线程将数据保存在数据库 + DataBaseManager.get.saveGasDensity(density, currentTime) + } + //时间作为X轴 + xAxisLabels.add(currentTime) + + //浓度作为Y轴 + val entry = Entry(i++.toFloat(), density.toFloat(), "浓度") + densityEntries.add(entry) + + //转化为控件需要的Data + dataSet = LineDataSet(densityEntries, "") + dataSet.setDrawCircles(false) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + //线条颜色 + dataSet.color = Color.RED + lineDataSets.add(dataSet) + lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + + //解决折线点太多导致卡顿问题 + if (lineData.entryCount > 50) { + lineData.removeDataSet(0) + lineData.notifyDataChanged() + } + binding.lineChart.data = lineData + binding.lineChart.invalidate() + } + } else { + Log.d(kTag, "onReceiveMessage: 数据校验失败") + } + } + }) + } + } } } @@ -663,111 +767,4 @@ } return super.onKeyDown(keyCode, event) } - - /***低功耗蓝牙********************************************/ - private val bleConnectListener = object : OnDeviceConnectListener { - override fun onConnecting(bluetoothGatt: BluetoothGatt?) { - Log.d(kTag, "onConnecting => ") - } - - override fun onConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - Log.d(kTag, "onConnectSuccess => $status") - } - - override fun onConnectFailure( - bluetoothGatt: BluetoothGatt?, exception: String, status: Int - ) { - Log.d(kTag, "onConnectFailure => $status") - isConnected = false - } - - override fun onDisConnecting(bluetoothGatt: BluetoothGatt?) { - Log.d(kTag, "onDisConnecting => ") - } - - override fun onDisConnectSuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - lifecycleScope.launch(Dispatchers.Main) { - Log.d(kTag, "onDisConnectSuccess => $status") - isConnected = false - binding.searchBleButton.text = "搜索蓝牙" - binding.stateView.text = "未连接" - binding.stateView.setTextColor(Color.RED) - } - } - - override fun onServiceDiscoverySuccess(bluetoothGatt: BluetoothGatt?, status: Int) { - lifecycleScope.launch(Dispatchers.Main) { - Log.d(kTag, "onServiceDiscoverySuccess => $status") - LoadingDialogHub.dismiss() - "连接成功".show(context) - isConnected = true - binding.searchBleButton.text = "断开连接" - binding.stateView.text = "已连接" - binding.stateView.setTextColor(Color.GREEN) - } - } - - override fun onServiceDiscoveryFailed(bluetoothGatt: BluetoothGatt?, msg: String) { - Log.d(kTag, "onServiceDiscoveryFailed => ") - isConnected = false - } - - override fun onReceiveMessage(bluetoothGatt: BluetoothGatt?, value: ByteArray) { - //[97, 97, 32, 48, 49, 32, 48, 48, 32, 48, 48, 32, 48, 48, 32, 48, 100, 32, 53, 53, 32] - if (value.check()) { - /***将值渲染到曲线图****************************************************************/ - lifecycleScope.launch(Dispatchers.Main) { - val currentTime = System.currentTimeMillis().timestampToTime() - //解析返回值 - val density = value.convertValue() - withContext(Dispatchers.IO) { - //协程切换为子线程将数据保存在数据库 - DataBaseManager.get.saveGasDensity(density, currentTime) - } - //时间作为X轴 - xAxisLabels.add(currentTime) - - //浓度作为Y轴 - val entry = Entry(i++.toFloat(), density.toFloat(), "浓度") - densityEntries.add(entry) - - //转化为控件需要的Data - dataSet = LineDataSet(densityEntries, "") - dataSet.setDrawCircles(false) - dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER - //线条颜色 - dataSet.color = Color.RED - lineDataSets.add(dataSet) - lineData = LineData(lineDataSets) - lineData.setDrawValues(false) - - //解决折线点太多导致卡顿问题 - if (lineData.entryCount > 50) { - lineData.removeDataSet(0) - lineData.notifyDataChanged() - } - binding.lineChart.data = lineData - binding.lineChart.invalidate() - } - } else { - Log.d(kTag, "onReceiveMessage: 数据校验失败") - } - } - - override fun onReceiveError(errorMsg: String) { - Log.d(kTag, "onReceiveError => $errorMsg") - } - - override fun onWriteSuccess(bluetoothGatt: BluetoothGatt?, msg: ByteArray?) { - Log.d(kTag, "onWriteSuccess => ${msg.contentToString()}") - } - - override fun onWriteFailed(bluetoothGatt: BluetoothGatt?, errorMsg: String) { - Log.d(kTag, "onWriteFailed => $errorMsg") - } - - override fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) { - Log.d(kTag, "onReadRssi => $rssi") - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/endoscope/widgets/BluetoothDeviceDialog.kt b/app/src/main/java/com/casic/endoscope/widgets/BluetoothDeviceDialog.kt index 0d8a791..1982004 100644 --- a/app/src/main/java/com/casic/endoscope/widgets/BluetoothDeviceDialog.kt +++ b/app/src/main/java/com/casic/endoscope/widgets/BluetoothDeviceDialog.kt @@ -2,7 +2,6 @@ import android.annotation.SuppressLint import android.app.Dialog -import android.bluetooth.BluetoothDevice import android.content.Context import android.graphics.Color import android.os.Bundle @@ -16,6 +15,7 @@ import android.widget.TextView import com.casic.endoscope.R import com.casic.endoscope.databinding.DialogBluetoothDeviceBinding +import com.clj.fastble.data.BleDevice import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.dp2px import com.pengxh.kt.lite.extensions.initDialogLayoutParams @@ -31,7 +31,7 @@ class Builder { lateinit var context: Context - lateinit var beans: ArrayList + lateinit var beans: ArrayList lateinit var negativeBtn: String lateinit var listener: OnDialogButtonClickListener @@ -40,7 +40,7 @@ return this } - fun setDeviceArray(beans: ArrayList): Builder { + fun setDeviceArray(beans: ArrayList): Builder { this.beans = beans return this }