diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
index b6b5281..9b87bcb 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
@@ -20,12 +20,6 @@
}
}
}
- BluetoothDevice.ACTION_ACL_CONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_CONNECTED)
- }
- BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_DISCONNECTED)
- }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
index b6b5281..9b87bcb 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
@@ -20,12 +20,6 @@
}
}
}
- BluetoothDevice.ACTION_ACL_CONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_CONNECTED)
- }
- BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_DISCONNECTED)
- }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
index 507655b..55549ec 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
@@ -15,13 +15,15 @@
const val PAGE_LIMIT = 15
const val BLUETOOTH_ON = 20
const val BLUETOOTH_OFF = 21
- const val DEVICE_CONNECTED = 22
- const val DEVICE_CONNECT_FAIL = 23
- const val DEVICE_DISCONNECTED = 24
+ const val CONNECT_SUCCESS = 22
+ const val CONNECT_FAILURE = 23
+ const val DISCONNECT_SUCCESS = 24
const val SEND_SUCCESS = 25
const val SEND_FAILURE = 26
const val RECEIVE_SUCCESS = 27
const val RECEIVE_FAILURE = 28
+ const val DISCOVERY_DEVICE = 29
+ const val DISCOVERY_OUT_TIME = 30
const val FIVE_YEARS = 5L * 365 * 60 * 60 * 24 * 1000L
const val IMAGE_MINUS_SIZE = 100 * 1024
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
index b6b5281..9b87bcb 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
@@ -20,12 +20,6 @@
}
}
}
- BluetoothDevice.ACTION_ACL_CONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_CONNECTED)
- }
- BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_DISCONNECTED)
- }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
index 507655b..55549ec 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
@@ -15,13 +15,15 @@
const val PAGE_LIMIT = 15
const val BLUETOOTH_ON = 20
const val BLUETOOTH_OFF = 21
- const val DEVICE_CONNECTED = 22
- const val DEVICE_CONNECT_FAIL = 23
- const val DEVICE_DISCONNECTED = 24
+ const val CONNECT_SUCCESS = 22
+ const val CONNECT_FAILURE = 23
+ const val DISCONNECT_SUCCESS = 24
const val SEND_SUCCESS = 25
const val SEND_FAILURE = 26
const val RECEIVE_SUCCESS = 27
const val RECEIVE_FAILURE = 28
+ const val DISCOVERY_DEVICE = 29
+ const val DISCOVERY_OUT_TIME = 30
const val FIVE_YEARS = 5L * 365 * 60 * 60 * 24 * 1000L
const val IMAGE_MINUS_SIZE = 100 * 1024
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
new file mode 100644
index 0000000..b0b05a0
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
@@ -0,0 +1,52 @@
+package com.casic.birmm.inspect.utils.callback
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
+
+
+interface OnBleConnectListener {
+ fun onConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在连接
+
+ fun onConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ status: Int
+ ) //连接成功
+
+ fun onConnectFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ exception: String?, status: Int
+ ) //连接失败
+
+ fun onDisConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在断开
+
+ fun onDisConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) // 断开连接
+
+
+ fun onServiceDiscoverySucceed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) //发现服务成功
+
+ fun onServiceDiscoveryFailed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: String?
+ ) //发现服务失败
+
+ fun onReceiveMessage(
+ bluetoothGatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) //收到消息
+
+ fun onReceiveError(errorMsg: String?) //接收数据出错
+
+ fun onWriteSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: ByteArray?
+ ) //写入成功
+
+ fun onWriteFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: ByteArray?, errorMsg: String?
+ ) //写入失败
+
+ fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) //成功读取到连接信号强度
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
index b6b5281..9b87bcb 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
@@ -20,12 +20,6 @@
}
}
}
- BluetoothDevice.ACTION_ACL_CONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_CONNECTED)
- }
- BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_DISCONNECTED)
- }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
index 507655b..55549ec 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
@@ -15,13 +15,15 @@
const val PAGE_LIMIT = 15
const val BLUETOOTH_ON = 20
const val BLUETOOTH_OFF = 21
- const val DEVICE_CONNECTED = 22
- const val DEVICE_CONNECT_FAIL = 23
- const val DEVICE_DISCONNECTED = 24
+ const val CONNECT_SUCCESS = 22
+ const val CONNECT_FAILURE = 23
+ const val DISCONNECT_SUCCESS = 24
const val SEND_SUCCESS = 25
const val SEND_FAILURE = 26
const val RECEIVE_SUCCESS = 27
const val RECEIVE_FAILURE = 28
+ const val DISCOVERY_DEVICE = 29
+ const val DISCOVERY_OUT_TIME = 30
const val FIVE_YEARS = 5L * 365 * 60 * 60 * 24 * 1000L
const val IMAGE_MINUS_SIZE = 100 * 1024
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
new file mode 100644
index 0000000..b0b05a0
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
@@ -0,0 +1,52 @@
+package com.casic.birmm.inspect.utils.callback
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
+
+
+interface OnBleConnectListener {
+ fun onConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在连接
+
+ fun onConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ status: Int
+ ) //连接成功
+
+ fun onConnectFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ exception: String?, status: Int
+ ) //连接失败
+
+ fun onDisConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在断开
+
+ fun onDisConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) // 断开连接
+
+
+ fun onServiceDiscoverySucceed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) //发现服务成功
+
+ fun onServiceDiscoveryFailed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: String?
+ ) //发现服务失败
+
+ fun onReceiveMessage(
+ bluetoothGatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) //收到消息
+
+ fun onReceiveError(errorMsg: String?) //接收数据出错
+
+ fun onWriteSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: ByteArray?
+ ) //写入成功
+
+ fun onWriteFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: ByteArray?, 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/birmm/inspect/utils/callback/OnDeviceSearchListener.kt b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnDeviceSearchListener.kt
new file mode 100644
index 0000000..af4d430
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnDeviceSearchListener.kt
@@ -0,0 +1,8 @@
+package com.casic.birmm.inspect.utils.callback
+
+import com.casic.birmm.inspect.bean.BlueToothBean
+
+interface OnDeviceSearchListener {
+ fun onDeviceFound(blueToothBean: BlueToothBean) //搜索到设备
+ fun onDiscoveryOutTime() //扫描超时
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5dd8db9..ff9af45 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -68,8 +68,6 @@
-
-
diff --git a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
index 14424ec..c842129 100644
--- a/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
+++ b/app/src/main/java/com/casic/birmm/inspect/bean/BlueToothBean.java
@@ -1,27 +1,29 @@
package com.casic.birmm.inspect.bean;
+import android.bluetooth.BluetoothDevice;
+
public class BlueToothBean {
- private String blueToothName;
- private String blueToothAddress;
+ private BluetoothDevice bluetoothDevice; //蓝牙设备
+ private int rssi; //蓝牙信号
- public BlueToothBean(String blueToothName, String blueToothAddress) {
- this.blueToothName = blueToothName;
- this.blueToothAddress = blueToothAddress;
+ public BlueToothBean(BluetoothDevice bluetoothDevice, int rssi) {
+ this.bluetoothDevice = bluetoothDevice;
+ this.rssi = rssi;
}
- public String getBlueToothName() {
- return blueToothName;
+ public BluetoothDevice getBluetoothDevice() {
+ return bluetoothDevice;
}
- public void setBlueToothName(String blueToothName) {
- this.blueToothName = blueToothName;
+ public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
+ this.bluetoothDevice = bluetoothDevice;
}
- public String getBlueToothAddress() {
- return blueToothAddress;
+ public int getRssi() {
+ return rssi;
}
- public void setBlueToothAddress(String blueToothAddress) {
- this.blueToothAddress = blueToothAddress;
+ public void setRssi(int rssi) {
+ this.rssi = rssi;
}
}
diff --git a/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
new file mode 100644
index 0000000..8b2ea6e
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/extensions/ByteArray.kt
@@ -0,0 +1,59 @@
+package com.casic.birmm.inspect.extensions
+
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.math.abs
+
+/**
+ * ByteArray扩展方法
+ */
+
+//ByteArray转16进制
+fun ByteArray.toHexString(hasSpace: Boolean = true) = this.joinToString("") {
+ (it.toInt() and 0xFF).toString(16).padStart(
+ 2,
+ '0'
+ ).toUpperCase(Locale.ROOT) + if (hasSpace) " " else ""
+}
+
+//ByteArray转ascii码字符串
+fun ByteArray.toAsciiString(): String {
+ val builder = StringBuilder()
+ for (index in 1..12) {
+ builder.append(this[index].toInt().toChar())
+ }
+ return builder.toString()
+}
+
+//ByteArray转十进制字符串集合
+fun ByteArray.toDecStringList(): ArrayList {
+ val data: ArrayList = ArrayList()
+ /**
+ * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
+ *
+ * 170是数据标头AA
+ * 13,10是数据结束位
+ * */
+ //AA 00 00 00 64 01 00 64 00 00 00 64 0D 0A
+ //浓度:4字节 0-99999
+ var potencyValue = 0
+ for (index in 1..4) {
+ potencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(potencyValue.toString())
+ //报警标志:1字节 0:未报警 1:报警
+ data.add(this[5].toString(10))
+ //报警值:2字节 0-65535
+ var alarmValue = 0
+ for (index in 6..7) {
+ alarmValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(alarmValue.toString())
+ //5s内最大值: 4字节 0-99999
+ var maxPotencyValue = 0
+ for (index in 8..11) {
+ maxPotencyValue += abs(this[index].toString(10).toInt())
+ }
+ data.add(maxPotencyValue.toString())
+ return data
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
new file mode 100644
index 0000000..a1fcddc
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BLEManager.kt
@@ -0,0 +1,484 @@
+package com.casic.birmm.inspect.utils
+
+import android.bluetooth.*
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Handler
+import android.util.Log
+import com.casic.birmm.inspect.bean.BlueToothBean
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
+import java.util.*
+
+
+/**
+ * 1、扫描设备
+ * 2、配对设备
+ * 3、解除设备配对
+ * 4、连接设备
+ * 6、发现服务
+ * 7、打开读写功能
+ * 8、数据通讯(发送数据、接收数据)
+ * 9、断开连接
+ */
+object BLEManager {
+ private const val Tag = "BLEManager"
+ private const val MAX_CONNECT_TIME = 10000L//连接超时时间10s
+ private var context: Context? = null
+ private var bluetoothManager: BluetoothManager? = null
+ private var bluetoothAdapter: BluetoothAdapter? = null
+ private val handler = Handler()
+ private var onDeviceSearchListener: OnDeviceSearchListener? = null
+ private var isConnecting = false
+ private lateinit var curConnectDevice: BluetoothDevice
+ private lateinit var serviceUUID: UUID
+ private lateinit var readUUID: UUID
+ private lateinit var writeUUID: UUID
+ private var onBleConnectListener: OnBleConnectListener? = null
+ private var bluetoothGatt: BluetoothGatt? = null
+ private var bluetoothGattService: BluetoothGattService? = null
+ private var readCharacteristic: BluetoothGattCharacteristic? = null
+ private var writeCharacteristic: BluetoothGattCharacteristic? = null
+
+ fun initBle(context: Context): Boolean {
+ this.context = context
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ if (bluetoothManager == null) {
+ return false
+ }
+ bluetoothAdapter = bluetoothManager!!.adapter
+ return bluetoothAdapter != null
+ } else {
+ return false
+ }
+ }
+
+ fun isEnable(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isEnabled
+ }
+
+ /**
+ * 打开蓝牙
+ * @param isFast true 直接打开蓝牙 false 提示用户打开
+ */
+ fun openBluetooth(context: Context, isFast: Boolean) {
+ if (!isEnable()) {
+ if (isFast) {
+ Log.d(Tag, "直接打开手机蓝牙")
+ bluetoothAdapter!!.enable()
+ } else {
+ context.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+ } else {
+ Log.d(Tag, "手机蓝牙状态已开")
+ }
+ }
+
+ /**
+ * 本地蓝牙是否处于正在扫描状态
+ * @return true false
+ */
+ fun isDiscovery(): Boolean {
+ if (bluetoothAdapter == null) {
+ return false
+ }
+ return bluetoothAdapter!!.isDiscovering
+ }
+
+ fun stopDiscoveryDevice() {
+ handler.removeCallbacks(stopScanRunnable)
+ if (bluetoothAdapter == null) {
+ return
+ }
+ bluetoothAdapter!!.stopLeScan(scanCallback)
+ }
+
+ private val stopScanRunnable = Runnable {
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDiscoveryOutTime() //扫描超时回调
+ }
+ //scanTime之后还没有扫描到设备,就停止扫描。
+ stopDiscoveryDevice()
+ }
+
+ //扫描设备回调
+ private val scanCallback = object : BluetoothAdapter.LeScanCallback {
+ override fun onLeScan(device: BluetoothDevice?, rssi: Int, scanRecord: ByteArray?) {
+ if (device == null) return
+ if (device.name != null) {
+ Log.d(Tag, device.name + "-->" + device.address)
+ if (onDeviceSearchListener != null) {
+ onDeviceSearchListener!!.onDeviceFound(BlueToothBean(device, rssi)) //扫描到设备回调
+ }
+ }
+ }
+ }
+
+ fun startDiscoveryDevice(onDeviceSearchListener: OnDeviceSearchListener, scanTime: Long) {
+ if (bluetoothAdapter == null) {
+ return
+ }
+ this.onDeviceSearchListener = onDeviceSearchListener
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ bluetoothAdapter!!.startLeScan(scanCallback)
+ } else {
+ return
+ }
+ //设定最长扫描时间
+ handler.postDelayed(stopScanRunnable, scanTime)
+ }
+
+ fun connectBleDevice(
+ context: Context, bluetoothDevice: BluetoothDevice,
+ outTime: Long, serviceUUID: String,
+ readUUID: String, writeUUID: String,
+ onBleConnectListener: OnBleConnectListener
+ ): BluetoothGatt? {
+ if (isConnecting) {
+ Log.d(Tag, "connectBleDevice()-->isConnecting = true")
+ return null
+ }
+ this.curConnectDevice = bluetoothDevice
+ this.serviceUUID = UUID.fromString(serviceUUID)
+ this.readUUID = UUID.fromString(readUUID)
+ this.writeUUID = UUID.fromString(writeUUID)
+ this.onBleConnectListener = onBleConnectListener
+ Log.d(Tag, "开始准备连接:" + bluetoothDevice.name + "-->" + bluetoothDevice.address)
+ try {
+ bluetoothGatt = bluetoothDevice.connectGatt(context, false, bluetoothGattCallback)
+ bluetoothGatt!!.connect()
+ isConnecting = true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ //设置连接超时时间10s
+ handler.postDelayed(connectOutTimeRunnable, outTime)
+ return bluetoothGatt
+ }
+
+ private val bluetoothGattCallback = object : BluetoothGattCallback() {
+ override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+ super.onConnectionStateChange(gatt, status, newState)
+ val bluetoothDevice = gatt!!.device
+ Log.d(Tag, "连接的设备:" + bluetoothDevice.name + " " + bluetoothDevice.address)
+ isConnecting = true
+ //移除连接超时
+ handler.removeCallbacks(connectOutTimeRunnable)
+ when (newState) {
+ BluetoothGatt.STATE_CONNECTING -> {
+ Log.d(Tag, "正在连接...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnecting(gatt, bluetoothDevice) //正在连接回调
+ }
+ }
+ BluetoothGatt.STATE_CONNECTED -> {
+ Log.d(Tag, "连接成功")
+ //连接成功去发现服务
+ gatt.discoverServices()
+ //设置发现服务超时时间
+ handler.postDelayed(serviceDiscoverOutTimeRunnable, MAX_CONNECT_TIME)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //连接成功回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTING -> {
+ Log.d(Tag, "正在断开...")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnecting(gatt, bluetoothDevice) //正在断开回调
+ }
+ }
+ BluetoothGatt.STATE_DISCONNECTED -> {
+ Log.d(Tag, "断开连接status: $status")
+ gatt.close()
+ when (status) {
+ 133 -> {
+ //无法连接
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接异常!",
+ status
+ ) //133连接异常 异常断开
+ Log.d(Tag, "连接失败status:" + status + " " + bluetoothDevice.address)
+ }
+ }
+ 62 -> {
+ if (onBleConnectListener != null) {
+ gatt.close()
+ onBleConnectListener!!.onConnectFailure(
+ gatt,
+ bluetoothDevice,
+ "连接成功服务未发现断开!",
+ status
+ )//62没有发现服务 异常断开
+ Log.d(Tag, "连接成功服务未发现断开status:$status")
+ }
+ }
+ 0 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //0正常断开 回调
+ }
+ }
+ 8 -> {//因为距离远或者电池无法供电断开连接
+ // 已经成功发现服务
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //8断电断开 回调
+ }
+ }
+ 34 -> {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //34断开
+ }
+ }
+ else -> {//其它断开连接
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onDisConnectSuccess(
+ gatt,
+ bluetoothDevice,
+ status
+ ) //其它断开
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
+ super.onServicesDiscovered(gatt, status)
+ //移除发现服务超时
+ handler.removeCallbacks(serviceDiscoverOutTimeRunnable)
+ //配置服务信息
+ if (setupService(gatt!!, serviceUUID, readUUID, writeUUID)) {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoverySucceed(
+ gatt,
+ gatt.device,
+ status
+ ) //成功发现服务回调
+ }
+ } else {
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onServiceDiscoveryFailed(
+ gatt,
+ gatt.device,
+ "获取服务特征异常"
+ ) //发现服务失败回调
+ }
+ }
+ }
+
+ //读取蓝牙设备发出来的数据回调
+ override fun onCharacteristicRead(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
+ ) {
+ super.onCharacteristicRead(gatt, characteristic, status)
+ Log.d(Tag, "读status: $status")
+ }
+
+ //向蓝牙设备写入数据结果回调
+ override fun onCharacteristicWrite(
+ gatt: BluetoothGatt?,
+ characteristic: BluetoothGattCharacteristic?,
+ status: Int
+ ) {
+ super.onCharacteristicWrite(gatt, characteristic, status)
+ if (characteristic!!.value == null) {
+ Log.e(Tag, "characteristic.getValue() == null");
+ return
+ }
+ //将收到的字节数组转换成十六进制字符串
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ //写入成功
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteSuccess(
+ gatt,
+ gatt!!.device,
+ characteristic.value
+ ) //写入成功回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> {
+ //写入失败
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onWriteFailure(
+ gatt,
+ gatt!!.device,
+ characteristic.value,
+ "写入失败"
+ ) //写入失败回调
+ }
+ }
+ BluetoothGatt.GATT_WRITE_NOT_PERMITTED -> {
+ Log.d(Tag, "没有权限")
+ }
+ }
+ }
+
+ override fun onCharacteristicChanged(
+ gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ super.onCharacteristicChanged(gatt, characteristic)
+ //接收数据
+ Log.d(Tag, "收到数据:" + characteristic!!.value)
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReceiveMessage(gatt, characteristic) //接收数据回调
+ } else {
+ Log.d(Tag, "onCharacteristicChanged-->onBleConnectListener == null: ")
+ }
+ }
+
+ override fun onDescriptorRead(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorRead(gatt, descriptor, status)
+ //开启监听成功,可以从设备读数据了
+ Log.d(Tag, "onDescriptorRead开启监听成功")
+ }
+
+ override fun onDescriptorWrite(
+ gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int
+ ) {
+ super.onDescriptorWrite(gatt, descriptor, status)
+ //开启监听成功,可以向设备写入命令了
+ Log.d(Tag, "onDescriptorWrite开启监听成功")
+ }
+
+ //蓝牙信号强度
+ override fun onReadRemoteRssi(gatt: BluetoothGatt?, rssi: Int, status: Int) {
+ super.onReadRemoteRssi(gatt, rssi, status)
+ when (status) {
+ BluetoothGatt.GATT_SUCCESS -> {
+ Log.w(Tag, "读取RSSI值成功,RSSI值: $rssi ,status: $status")
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onReadRssi(gatt, rssi, status) //成功读取连接的信号强度回调
+ }
+ }
+ BluetoothGatt.GATT_FAILURE -> Log.w(Tag, "读取RSSI值失败,status: $status")
+ }
+ }
+ }
+
+ private val connectOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "connectOutTimeRunnable-->bluetoothGatt == null")
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //连接超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "连接超时",
+ -1
+ ) //连接失败回调
+ }
+ }
+
+ private val serviceDiscoverOutTimeRunnable = Runnable {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "serviceDiscoverOutTimeRunnable-->bluetoothGatt == null");
+ return@Runnable
+ }
+ isConnecting = false
+ bluetoothGatt!!.disconnect()
+ //发现服务超时当作连接失败回调
+ if (onBleConnectListener != null) {
+ onBleConnectListener!!.onConnectFailure(
+ bluetoothGatt,
+ curConnectDevice,
+ "发现服务超时!",
+ -1
+ ); //连接失败回调
+ }
+ }
+
+ private fun setupService(
+ bluetoothGatt: BluetoothGatt, serviceUUID: UUID, readUUID: UUID, writeUUID: UUID
+ ): Boolean {
+ var notifyCharacteristic: BluetoothGattCharacteristic? = null
+ bluetoothGatt.services.forEach { service ->
+ if (service.uuid == serviceUUID) {
+ bluetoothGattService = service
+ bluetoothGattService!!.characteristics.forEach { characteristic ->
+ val charaProp = characteristic.properties
+ if (characteristic.uuid == readUUID) { //读特征
+ readCharacteristic = characteristic
+ }
+ if (characteristic.uuid == writeUUID) { //写特征
+ writeCharacteristic = characteristic
+ }
+ if (charaProp and BluetoothGattCharacteristic.PROPERTY_NOTIFY > 0) {
+ val notifyServiceUUID = bluetoothGattService!!.uuid
+ val notifyCharacteristicUUID = characteristic.uuid
+ Log.d(
+ Tag,
+ "notifyCharacteristicUUID=$notifyCharacteristicUUID, notifyServiceUUID=$notifyServiceUUID"
+ )
+ notifyCharacteristic = bluetoothGatt.getService(notifyServiceUUID)
+ .getCharacteristic(notifyCharacteristicUUID)
+ }
+ }
+ }
+ }
+ //打开读通知,打开的是notifyCharacteristic!!!,不然死活不走onCharacteristicChanged回调
+ bluetoothGatt.setCharacteristicNotification(notifyCharacteristic, true)
+ //一定要重新设置
+ for (descriptor in notifyCharacteristic!!.descriptors) {
+ descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
+ bluetoothGatt.writeDescriptor(descriptor)
+ }
+ //延迟2s,保证所有通知都能及时打开
+ handler.postDelayed({ }, 2000)
+ return true
+ }
+
+ fun sendCommand(cmd: ByteArray): Boolean {
+ if (writeCharacteristic == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->writeGattCharacteristic == null")
+ return false
+ }
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "sendCommand(ByteArray)-->bluetoothGatt == null")
+ return false
+ }
+ val value = writeCharacteristic!!.setValue(cmd)
+ Log.d(Tag, "写特征设置值结果:$value")
+ return bluetoothGatt!!.writeCharacteristic(writeCharacteristic)
+ }
+
+ fun disConnectDevice() {
+ if (bluetoothGatt == null) {
+ Log.d(Tag, "disConnectDevice(ByteArray)-->bluetoothGatt == null");
+ return
+ }
+ bluetoothGatt!!.disconnect()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
index b6b5281..9b87bcb 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/BluetoothStateBroadcastReceiver.kt
@@ -20,12 +20,6 @@
}
}
}
- BluetoothDevice.ACTION_ACL_CONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_CONNECTED)
- }
- BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
- MapActivity.sendEmptyMessage(Constant.DEVICE_DISCONNECTED)
- }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
index 507655b..55549ec 100644
--- a/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/Constant.kt
@@ -15,13 +15,15 @@
const val PAGE_LIMIT = 15
const val BLUETOOTH_ON = 20
const val BLUETOOTH_OFF = 21
- const val DEVICE_CONNECTED = 22
- const val DEVICE_CONNECT_FAIL = 23
- const val DEVICE_DISCONNECTED = 24
+ const val CONNECT_SUCCESS = 22
+ const val CONNECT_FAILURE = 23
+ const val DISCONNECT_SUCCESS = 24
const val SEND_SUCCESS = 25
const val SEND_FAILURE = 26
const val RECEIVE_SUCCESS = 27
const val RECEIVE_FAILURE = 28
+ const val DISCOVERY_DEVICE = 29
+ const val DISCOVERY_OUT_TIME = 30
const val FIVE_YEARS = 5L * 365 * 60 * 60 * 24 * 1000L
const val IMAGE_MINUS_SIZE = 100 * 1024
diff --git a/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
new file mode 100644
index 0000000..b0b05a0
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnBleConnectListener.kt
@@ -0,0 +1,52 @@
+package com.casic.birmm.inspect.utils.callback
+
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
+
+
+interface OnBleConnectListener {
+ fun onConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在连接
+
+ fun onConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ status: Int
+ ) //连接成功
+
+ fun onConnectFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ exception: String?, status: Int
+ ) //连接失败
+
+ fun onDisConnecting(bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?) //正在断开
+
+ fun onDisConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) // 断开连接
+
+
+ fun onServiceDiscoverySucceed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) //发现服务成功
+
+ fun onServiceDiscoveryFailed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: String?
+ ) //发现服务失败
+
+ fun onReceiveMessage(
+ bluetoothGatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) //收到消息
+
+ fun onReceiveError(errorMsg: String?) //接收数据出错
+
+ fun onWriteSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, msg: ByteArray?
+ ) //写入成功
+
+ fun onWriteFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: ByteArray?, 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/birmm/inspect/utils/callback/OnDeviceSearchListener.kt b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnDeviceSearchListener.kt
new file mode 100644
index 0000000..af4d430
--- /dev/null
+++ b/app/src/main/java/com/casic/birmm/inspect/utils/callback/OnDeviceSearchListener.kt
@@ -0,0 +1,8 @@
+package com.casic.birmm.inspect.utils.callback
+
+import com.casic.birmm.inspect.bean.BlueToothBean
+
+interface OnDeviceSearchListener {
+ fun onDeviceFound(blueToothBean: BlueToothBean) //搜索到设备
+ fun onDiscoveryOutTime() //扫描超时
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/birmm/inspect/view/MapActivity.kt b/app/src/main/java/com/casic/birmm/inspect/view/MapActivity.kt
index dab7f0c..9e21422 100644
--- a/app/src/main/java/com/casic/birmm/inspect/view/MapActivity.kt
+++ b/app/src/main/java/com/casic/birmm/inspect/view/MapActivity.kt
@@ -1,9 +1,9 @@
package com.casic.birmm.inspect.view
-import android.bluetooth.BluetoothAdapter
+import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
-import android.content.BroadcastReceiver
-import android.content.Context
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
import android.content.Intent
import android.os.Bundle
import android.os.Handler
@@ -22,10 +22,14 @@
import com.casic.birmm.inspect.bean.InspectionBean
import com.casic.birmm.inspect.extensions.id
import com.casic.birmm.inspect.extensions.show
+import com.casic.birmm.inspect.extensions.toAsciiString
+import com.casic.birmm.inspect.extensions.toDecStringList
import com.casic.birmm.inspect.model.TaskRecordModel
import com.casic.birmm.inspect.model.UserInfoModel
import com.casic.birmm.inspect.utils.*
import com.casic.birmm.inspect.utils.callback.ILocationListener
+import com.casic.birmm.inspect.utils.callback.OnBleConnectListener
+import com.casic.birmm.inspect.utils.callback.OnDeviceSearchListener
import com.casic.birmm.inspect.vm.TaskRecordViewModel
import com.casic.birmm.inspect.widgets.InputDialog
import com.casic.birmm.inspect.widgets.SingleChoiceDialog
@@ -64,10 +68,9 @@
private var routes: MutableList = ArrayList()//路线集和
private var gson: Gson = Gson()
private var isBluetoothOn = true
- private var blueToothDevices: MutableList = ArrayList()
private var blueToothBeans: MutableList = ArrayList()//搜索展示列表
- private var bluetoothAdapter: BluetoothAdapter? = null
private var currentDevice: BluetoothDevice? = null// 当前蓝牙设备
+ private var curConnectState = false
init {
weakReferenceHandler = WeakReferenceHandler(this)
@@ -75,6 +78,7 @@
private class WeakReferenceHandler(activity: MapActivity) : Handler() {
private val activity: WeakReference = WeakReference(activity)
+ @SuppressLint("SetTextI18n")
override fun handleMessage(msg: Message) {
val mapActivity = activity.get() ?: return
when (msg.what) {
@@ -88,27 +92,92 @@
mapActivity.bluetoothButton.setImageResource(R.drawable.ic_bluetooth_disabled)
mapActivity.isBluetoothOn = false
}
- Constant.DEVICE_CONNECTED -> {
- //TODO 设备已连接
- mapActivity.communicateWithDevice(Constant.ASK_DEV_CODE_COMMAND)
+ Constant.DISCOVERY_DEVICE -> {
+ val bean = msg.obj as BlueToothBean
+ if (mapActivity.blueToothBeans.size == 0) {
+ mapActivity.blueToothBeans.add(bean)
+ } else {
+ //0表示未添加到list的新设备,1表示已经扫描并添加到list的设备
+ var judge = 0
+ for (it in mapActivity.blueToothBeans) {
+ if (it.bluetoothDevice.address == bean.bluetoothDevice.address) {
+ judge = 1
+ break
+ }
+ }
+ if (judge == 0) {
+ mapActivity.blueToothBeans.add(bean)
+ }
+ }
}
- Constant.DEVICE_CONNECT_FAIL -> {
- //TODO 设备连接失败/超时
+ Constant.DISCOVERY_OUT_TIME -> {
+ OtherUtils.dismissLoadingDialog()
+ val sheetBuilder =
+ QMUIBottomSheet.BottomListSheetBuilder(mapActivity)
+ sheetBuilder.setTitle("请选择要连接的设备")
+ mapActivity.blueToothBeans.forEach {
+ sheetBuilder.addItem(it.bluetoothDevice.name)
+ }
+ sheetBuilder.setGravityCenter(true).setAddCancelBtn(true)
+ .setOnSheetItemClickListener { dialog, _, position, _ ->
+ dialog.dismiss()
+ //连接点击的设备
+ mapActivity.startConnectDevice(
+ mapActivity.blueToothBeans[position].bluetoothDevice
+ )
+ }.build().show()
}
- Constant.DEVICE_DISCONNECTED -> {
- //TODO 设备断开连接
+ Constant.CONNECT_SUCCESS -> {
+ OtherUtils.dismissLoadingDialog()
+ mapActivity.curConnectState = true
+ BLEManager.sendCommand(Constant.ASK_DEV_CODE_COMMAND)
+ }
+ Constant.CONNECT_FAILURE -> {
+ mapActivity.curConnectState = false
}
Constant.SEND_SUCCESS -> {
- //TODO 发送成功
+ val sendSuccess = msg.obj as ByteArray
+ Log.d(Tag, "发送成功->sendSuccessBuffer: ${sendSuccess.toList()}")
}
Constant.SEND_FAILURE -> {
- //TODO 发送失败
+ val sendFail = msg.obj as ByteArray
+ Log.d(Tag, "发送失败->sendFailBuffer: ${sendFail.toList()}")
}
Constant.RECEIVE_SUCCESS -> {
//TODO 接收成功
+ val receiveByteArray = msg.obj as ByteArray
+ //根据返回值标头判断是设备编号还是数据值
+ val firstByte = receiveByteArray[0]
+ if (firstByte == 0xAA.toByte()) {
+ //解析测量数据
+ if (receiveByteArray.size == 14) {
+ val dataList = receiveByteArray.toDecStringList()
+ /**
+ * [100, 1, 100, 100]
+ * */
+ mapActivity.currentValueView.text = dataList[0]
+ mapActivity.settingsValueView.text = dataList[2]
+ mapActivity.maxValueView.text = dataList[3]
+ } else {
+ Log.d(Tag, "设备返回值长度异常,无法解析")
+ }
+ } else {
+ //解析deviceCode
+ if (receiveByteArray.size >= 12) {
+ mapActivity.deviceStatusView.text =
+ "设备编号: ${receiveByteArray.toAsciiString()}"
+ BLEManager.sendCommand(Constant.OPEN_TRANSFER_COMMAND)
+ } else {
+ Log.d(Tag, "设备返回值长度异常,无法解析")
+ }
+ }
}
Constant.RECEIVE_FAILURE -> {
- //TODO 接收失败
+ val receiveString = msg.obj as String
+ Log.d(Tag, "接收失败->receiveString: $receiveString")
+ }
+ Constant.DISCONNECT_SUCCESS -> {
+ mapActivity.curConnectState = false
}
}
}
@@ -138,128 +207,123 @@
fun initData() {
val userModelJson = SaveKeyValues.getValue(Constant.USER_OBJECT, "") as String
userDataModel = gson.fromJson(userModelJson, UserInfoModel::class.java).data!!
- //蓝牙搜索监听
- BroadcastManager.instance.addAction(
- arrayOf(
- BluetoothDevice.ACTION_FOUND,
- BluetoothAdapter.ACTION_DISCOVERY_FINISHED
- ), object : BroadcastReceiver() {
- override fun onReceive(context: Context?, intent: Intent?) {
- when (intent?.action) {
- BluetoothDevice.ACTION_FOUND -> {
- val device =
- intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
- lateinit var bean: BlueToothBean
- device?.let {
- bean = if (it.name == null || it.name == "") {
- BlueToothBean("设备名未知", it.address)
- } else {
- BlueToothBean(device.name, device.address)
- }
- }
- if (bean.blueToothName != "设备名未知") {
- if (blueToothBeans.size == 0) {
- blueToothBeans.add(bean)
- blueToothDevices.add(device)
- } else {
- //0表示未添加到list的新设备,1表示已经扫描并添加到list的设备
- var judge = 0
- for (it in blueToothBeans) {
- if (it.blueToothAddress == bean.blueToothAddress) {
- judge = 1
- break
- }
- }
- if (judge == 0) {
- blueToothBeans.add(bean)
- blueToothDevices.add(device)
- }
- }
- }
- }
- BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
- OtherUtils.dismissLoadingDialog()
- bluetoothButton.isEnabled = true
- Log.d(Tag, gson.toJson(blueToothBeans))
- val sheetBuilder =
- QMUIBottomSheet.BottomListSheetBuilder(this@MapActivity)
- sheetBuilder.setTitle("请选择要连接的设备")
- blueToothBeans.forEach {
- sheetBuilder.addItem(it.blueToothName)
- }
- sheetBuilder.setGravityCenter(true).setAddCancelBtn(true)
- .setOnSheetItemClickListener { dialog, _, position, _ ->
- dialog.dismiss()
- //连接点击的设备
- startConnectDevice(
- blueToothBeans[position].blueToothName,
- blueToothDevices[position]
- )
- }.build().show()
- }
- }
- }
- })
+
+ if (BLEManager.initBle(this)) {
+ if (BLEManager.isEnable()) {
+ BLEManager.openBluetooth(this, false)
+ }
+ } else {
+ "该设备不支持低功耗蓝牙".show(this)
+ }
}
- private fun startConnectDevice(deviceName: String, bluetoothDevice: BluetoothDevice?) {
- if (bluetoothDevice == null) {
- Log.d(Tag, "startConnectDevice-->bluetoothDevice == null")
- return
+ private fun startConnectDevice(device: BluetoothDevice) {
+ this.currentDevice = device
+ if (!curConnectState) {
+ OtherUtils.showLoadingDialog(this, "正在连接[${currentDevice!!.name}]...")
+ BLEManager.connectBleDevice(
+ this, currentDevice!!, 15000,
+ Constant.SERVICE_UUID,
+ Constant.READ_CHARACTERISTIC_UUID,
+ Constant.WRITE_CHARACTERISTIC_UUID,
+ onBleConnectListener
+ )
}
- this.currentDevice = bluetoothDevice
- if (bluetoothAdapter == null) {
- Log.d(Tag, "startConnectDevice-->bluetoothAdapter == null")
- return
- }
- OtherUtils.showLoadingDialog(this, "正在连接[$deviceName]...")
-
}
-// private fun manageConnectSendReceiveData(bluetoothSocket: BluetoothSocket) {
-// connectedThread = ConnectedThread(bluetoothSocket)
-// connectedThread!!.start()
-// connectedThread!!.setOnSendReceiveDataListener(object :
-// ConnectedThread.OnSendReceiveDataListener {
-// override fun onSendDataSuccess(data: ByteArray?) {
-// val message = weakReferenceHandler.obtainMessage()
-// message.what = Constant.SEND_SUCCESS
-// message.obj = "发送数据成功,长度" + data!!.size + "->" + ConnectedThread.bytes2HexString(
-// data,
-// data.size
-// )
-// weakReferenceHandler.sendMessage(message)
-// }
-//
-// override fun onSendDataError(data: ByteArray?, errorMsg: String?) {
-// val message = weakReferenceHandler.obtainMessage()
-// message.what = Constant.SEND_FAILURE
-// message.obj = "发送数据出错,长度" + data!!.size + "->" + ConnectedThread.bytes2HexString(
-// data,
-// data.size
-// )
-// weakReferenceHandler.sendMessage(message)
-// }
-//
-// override fun onReceiveDataSuccess(buffer: ByteArray?) {
-// val message = weakReferenceHandler.obtainMessage()
-// message.what = Constant.RECEIVE_SUCCESS
-// message.obj =
-// "成功接收数据,长度" + buffer!!.size + "->" + ConnectedThread.bytes2HexString(
-// buffer,
-// buffer.size
-// )
-// weakReferenceHandler.sendMessage(message)
-// }
-//
-// override fun onReceiveDataError(errorMsg: String?) {
-// val message = weakReferenceHandler.obtainMessage()
-// message.what = Constant.RECEIVE_FAILURE
-// message.obj = "接收数据出错:$errorMsg"
-// weakReferenceHandler.sendMessage(message)
-// }
-// })
-// }
+ private val onBleConnectListener = object : OnBleConnectListener {
+ override fun onConnecting(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?
+ ) {
+ }
+
+ override fun onConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?, status: Int
+ ) {
+ }
+
+ override fun onConnectFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ exception: String?, status: Int
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.CONNECT_FAILURE
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onDisConnecting(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?
+ ) {
+
+ }
+
+ override fun onDisConnectSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ status: Int
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.DISCONNECT_SUCCESS
+ message.obj = status
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onServiceDiscoverySucceed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ status: Int
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.CONNECT_SUCCESS
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onServiceDiscoveryFailed(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: String?
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.CONNECT_FAILURE
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onReceiveMessage(
+ bluetoothGatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.RECEIVE_SUCCESS
+ message.obj = characteristic!!.value
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onReceiveError(errorMsg: String?) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.RECEIVE_FAILURE
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onWriteSuccess(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: ByteArray?
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.SEND_SUCCESS
+ message.obj = msg
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onWriteFailure(
+ bluetoothGatt: BluetoothGatt?, bluetoothDevice: BluetoothDevice?,
+ msg: ByteArray?, errorMsg: String?
+ ) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.SEND_FAILURE
+ message.obj = msg
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onReadRssi(bluetoothGatt: BluetoothGatt?, rssi: Int, status: Int) {
+
+ }
+ }
private fun initMap(savedInstanceState: Bundle?) {
mapView.onCreate(savedInstanceState)
@@ -319,47 +383,56 @@
}
private fun menuButtonEvent() {
- //判断蓝牙的状态
- bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
- if (bluetoothAdapter == null) {
- "该设备不支持蓝牙,无法连接".show(this)
- return
- }
- if (bluetoothAdapter!!.isEnabled) {
+ //蓝牙按钮
+ if (isBluetoothOn) {
bluetoothButton.setImageResource(R.drawable.ic_bluetooth_enable)
bluetoothButton.setOnClickListener {
- if (currentDevice == null) {
- //搜索蓝牙
- searchDevice()
+ if (curConnectState) {
+ //断开连接
+ BLEManager.disConnectDevice()
+ currentValueView.text = "--"
+ settingsValueView.text = "--"
+ maxValueView.text = "--"
+ deviceStatusView.text = "设备编号:未连接"
+ "设备已断开连接".show(this)
} else {
- if (currentDevice!!.bondState == BluetoothDevice.BOND_NONE) {
- searchDevice()
- } else {
- //断开连接
- currentValueView.text = "--"
- settingsValueView.text = "--"
- maxValueView.text = "--"
- deviceStatusView.text = "设备编号:未连接"
- "设备已断开连接".show(this)
- }
+ searchDevice()
}
}
} else {
bluetoothButton.setImageResource(R.drawable.ic_bluetooth_disabled)
- //打开
- startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
+ }
+
+ //重新发送指令按钮
+ refreshButton.setOnClickListener {
+ if (curConnectState) {
+ BLEManager.sendCommand(Constant.OPEN_TRANSFER_COMMAND)
+ } else {
+ "请先连接设备".show(this)
+ }
}
}
private fun searchDevice() {
//搜索蓝牙
- if (bluetoothAdapter!!.isDiscovering) {
- //搜索中不让再次搜索
- bluetoothButton.isEnabled = false
- return
+ if (BLEManager.isDiscovery()) {//当前正在搜索设备...
+ BLEManager.stopDiscoveryDevice()
}
OtherUtils.showLoadingDialog(this, "设备搜索中...");
- bluetoothAdapter!!.startDiscovery()
+ BLEManager.startDiscoveryDevice(object : OnDeviceSearchListener {
+ override fun onDeviceFound(blueToothBean: BlueToothBean) {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.DISCOVERY_DEVICE
+ message.obj = blueToothBean
+ weakReferenceHandler.sendMessage(message)
+ }
+
+ override fun onDiscoveryOutTime() {
+ val message = weakReferenceHandler.obtainMessage()
+ message.what = Constant.DISCOVERY_OUT_TIME
+ weakReferenceHandler.sendMessage(message)
+ }
+ }, 15 * 1000)
}
private fun selectInspectMode() {
@@ -434,17 +507,13 @@
}
})
updateCurrentInspection()
- // 和设备通信
- communicateWithDevice(Constant.OPEN_TRANSFER_COMMAND)
}
private fun updateCurrentInspection() {
SaveKeyValues.putValue(Constant.INSPECTION_OBJECT, gson.toJson(inspectionBean))
}
- private fun communicateWithDevice(cmd: ByteArray) {
-
- }
+ /***以下是地图生命周期管理************************************************************************/
override fun onResume() {
super.onResume()
@@ -465,5 +534,6 @@
cancel()
super.onDestroy()
mapView.onDestroy()
+ BroadcastManager.instance.destroy()
}
}
\ No newline at end of file