我想知道如何实现这个
要实现多个BLE连接,您需要存储多个BluetoothGatt
对象,并将这些对象用于不同的设备。要存储多个BluetoothGatt
连接对象,可以使用Map<>
。
private Map<String, BluetoothGatt> connectedDeviceMap;
在 Service 的 onCreate
方法中初始化 Map
connectedDeviceMap = new HashMap<String, BluetoothGatt>();
在调用device.connectGatt(this, false, mGattCallbacks);
连接GATT服务器之前,请检查设备是否已连接。
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
int connectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT);
if(connectionState == BluetoothProfile.STATE_DISCONNECTED ){
// connect your device
device.connectGatt(this, false, mGattCallbacks);
}else if( connectionState == BluetoothProfile.STATE_CONNECTED ){
// already connected . send Broadcast if needed
}
如果 BluetoothGattCallback
的连接状态为 CONNECTED,则将 BluetoothGatt
对象存储在 Map
中,如果连接状态为 DISCONNECTED,则从 Map
中移除它。
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
BluetoothDevice device = gatt.getDevice();
String address = device.getAddress();
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i(TAG, "Connected to GATT server.");
if (!connectedDeviceMap.containsKey(address)) {
connectedDeviceMap.put(address, gatt);
}
// Broadcast if needed
Log.i(TAG, "Attempting to start service discovery:" +
gatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i(TAG, "Disconnected from GATT server.");
if (connectedDeviceMap.containsKey(address)){
BluetoothGatt bluetoothGatt = connectedDeviceMap.get(address);
if( bluetoothGatt != null ){
bluetoothGatt.close();
bluetoothGatt = null;
}
connectedDeviceMap.remove(address);
}
// Broadcast if needed
}
}
类似的,在onServicesDiscovered(BluetoothGatt gatt, int status)
方法中,您可以在参数中得到一个BluetoothGatt
连接对象,并从那个BluetoothGatt
获取设备。还有其他回调方法,比如public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
,您将从gatt
获得设备。
当需要writeCharacteristic或writeDescriptor时,请从Map
获取BluetoothGatt
对象,然后使用该BluetoothGatt
对象为不同的连接调用gatt.writeCharacteristic(characteristic)
和gatt.writeDescriptor(descriptor)
。
每个连接都需要单独的线程吗?
我认为您并不需要为每个连接使用单独的Thread。只需在后台线程上运行Service
即可。
希望这可以帮助到您。
我从Gatt客户端(中央)这一侧看到了答案。但是,如果你在外围设备这一侧并且需要连接多个中央设备,那么解决这个问题的方法甚至更加简单。
只需像下面提到的那样将它们的地址保留在一个arrayListOf
中:
var connectedDevices = arrayListOf<BluetoothDevice>()
当通知特征变化(发送)时,只需指出要发送到的特定设备:
fun send(content: String, deviceIndex: Int) {
characteristic.setValue(content)
Log.i("NOTIFY",
"notifyCharacteristicChanged called: ${
gattServer.notifyCharacteristicChanged(connectedDevicesArray[deviceIndex],
characteristics,
true)}")
}
Abu Yousuf的回答真的帮了我很多,尤其是因为我在互联网上找不到类似的东西。 我想补充一件我曾经苦恼过的事情:最好不要将你的BluetoothGattCharacteristic保存在全局变量中,因为它对于每个连接的设备都是唯一且不同的。 所以最好在每个操作中检索它,例如当您想要写入新值时:
BluetoothGatt gatt = connectedDeviceMap.get(address);
BluetoothGattCharacteristic localChar = gatt.getService(SERVICE_UUID).getCharacteristic(CHAR_UUID);
localChar.setValue(value);
gatt.writeCharacteristic(localChar);
gatt
并使用该gatt
设置通知。我认为读取数据不需要延迟。 - Abu Yousuf