蓝牙权限在各个版本中略有不同
<!-- Android 12 及以上版本 -->
<!-- 如果明确不需要蓝牙推断位置的话,可以通过标记 usesPermissionFlags=“neverForLocation” -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<!-- Android 11 及以下版本 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30"/>
<!-- Android 9 及以下版本 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28"/>
//获取蓝牙适配器
val bleAdapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
//监听返回数据
private val bleScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult?) {
if (result != null){
Log.e("bleLog", "startScanResult = $result")
}
}
}
/**
* 开启扫描
*/
bleAdapter.bluetoothLeScanner.startScan(bleScanCallback)
/**
* 结束扫描
*/
bleAdapter.bluetoothLeScanner.stopScan(bleScanCallback)
private var mBleGatt : BluetoothGatt? = null
//连接过程与数据接收回调
private val bleGattCallback = object : BluetoothGattCallback() {
//连接状态变更
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
if (newState == BluetoothProfile.STATE_CONNECTED){
//已连接
//发现服务
mBleGatt?.discoverServices()
}else if (newState == BluetoothProfile.STATE_DISCONNECTED){
//已断开连接
}
}
//发现服务回调
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
// 调用 mBleGatt?.discoverServices() 时触发该回调
if (status != BluetoothGatt.GATT_SUCCESS){
//失败
return
}
//获取指定GATT服务,UUID 由远程设备提供
val bleGattService = mBleGatt?.getService(UUID.fromString("8888888"))
//获取指定GATT特征,UUID 由远程设备提供
val bleGattCharacteristic = bleGattService?.getCharacteristic(UUID.fromString("777777"))
//启用特征通知,如果远程设备修改了特征,则会触发 onCharacteristicChange() 回调
mBleGatt?.setCharacteristicNotification(bleGattCharacteristic, true)
//启用客户端特征配置【固定写法】
val bleGattDescriptor = bleGattCharacteristic?.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))
bleGattDescriptor?.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
mBleGatt?.writeDescriptor(bleGattDescriptor)
}
//启用客户端特征配置结果回调
override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS ){
//此时蓝牙设备连接才算真正连接成功,即具备读写数据的能力
}
}
//App修改特征回调,即 App 给设备发送数据结果回调
override fun onCharacteristicWrite(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int
) {
if (status == BluetoothGatt.GATT_SUCCESS){
//数据写入完成
// 调用 characteristic?.value 得到的 ByteArray 与 发送数据一样
}
}
//远程设备修改特征描述回调,即设备给 App 发送数据
override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?
) {
//调用 characteristic?.value 获取远程设备发送过来的数据
}
}
/**
* 开始连接
* @param deviceMac 设备Mac地址
*/
val bleDevice = bleAdapter.getRemoteDevice(deviceMac)
mBleGatt = bleDevice.connectGatt(context, false, bleGattCallback, BluetoothDevice.TRANSPORT_LE)
/**
* 断开连接
*/
mBleGatt?.disconnect()
mBleGatt?.close()
mBleGattCharacteristic?.value = data
mBleGatt?.writeCharacteristic(mBleGattCharacteristic)
记住一个核心:蓝牙传输非常不稳定,指不定啥时候就没响应或丢包了。
背景:我手里的远端设备是一款实时操作系统的智能穿戴设备。该设备有一个特点:只能处理一条指令,处理完成后等待下一条,如果同时来多条,则只能处理第一条。
Android Studio 打印日志或断点时,会自动将 16 进制 转成 10 进制进行显示。
十进制数 除以 16 取余,然后从低往上输出。例如:1758 = 0x6DE
位数指向的数 * 16^位数 相加之和。例如 0x2A7F = 10879
记住常用数转化:例如, 45 = (32 + 8 + 4 + 1) = 101101
十进制 | 二进制 |
---|---|
1 (2^0) | 01 |
2 (2^1) | 10 |
4 (2^2) | 100 |
8 (2^3) | 1000 |
16 (2^4) | 10000 |
32 (2^5) | 100000 |
64 (2^6) | 1000000 |
位数指向的数 * 2^位数 相加之和。例如 10010 = 18
按每位数单独转二进制。例如: 0x6DA2 = 110110110100010
每四位一组,每组转 16 进制,然后拼接。例如: 101010110 = 0x156
都为 1 时才是1
**只要有 1 **时就是 1
**只有一个 1 **时才是 1
1 变 0, 0 变 1
除以2^右移位数。例如: 75 >> 3 = 9
乘以 2^ 左移位数。例如: 75 << 3 = 600
Android 12 中的新蓝牙权限
蓝牙概览 | Connectivity | Android Developers
蓝牙智能设备数据采集平台化方案 | 京东云技术团队 - 掘金
BLE低功耗蓝牙技术详解
Android蓝牙通信机制详解 - 掘金
Hi,我是“青杉”,您可以通过如下方式关注我: