Android BLE 多连接

Android BLE multiple connections

我正在尝试创建一个连接多个蓝牙低功耗设备并从其接收通知的应用程序。我想知道如何实现这一目标。每个连接都需要一个单独的线程吗?考虑到 API 的异步性质,我如何才能确保发现服务和设置通知的顺序有效。我目前正在使用此处提供的相同结构: https://developer.android.com/guide/topics/connectivity/bluetooth-le.html。这仅为单个连接设置。我能否保留此结构,即扩展 BluetoothLeService class 中的服务 class 并绑定到该服务。我最近发现服务 class 是一个单例,所以我将如何创建我的 BluetootLeService class 的不同实例并接收广播并注册广播 Receiver/Receivers 以处理来自适当的更改设备。

I am wondering how this can be achieved

要实现多个 BLE 连接,您必须存储多个 BluetoothGatt 对象并将这些对象用于不同的设备。要存储 BluetoothGatt 的多个连接对象,您可以使用 Map<>

private Map<String, BluetoothGatt> connectedDeviceMap; 

On 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
  }

On 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

当您需要 writeCharacteristicwriteDescriptor 时,从 Map 获取 BluetoothGatt 对象并使用那个 BluetoothGatt 为不同的连接调用 gatt.writeCharacteristic(characteristic) gatt.writeDescriptor(descriptor) 的对象。

Do I need a separate thread for each connection?

我认为您不需要为每个连接使用单独的 线程。只是 运行 后台线程上的 Service

希望对您有所帮助。

Abu Yousuf 的回答对我很有帮助,也是因为我在网上找不到类似的东西。 我想补充一件让我苦恼的事情:最好 而不是 将您的 BluetoothGattCharacteristic 保存在一个全局变量中,因为它对于每个连接的设备都是唯一且不同的。 因此,宁愿在每个动作中检索它,例如当你想写一个新值时:

BluetoothGatt gatt = connectedDeviceMap.get(address);
BluetoothGattCharacteristic localChar = gatt.getService(SERVICE_UUID).getCharacteristic(CHAR_UUID);
localChar.setValue(value);
gatt.writeCharacteristic(localChar);