【问题标题】:Android BLE multiple connectionsAndroid BLE 多连接
【发布时间】:2017-11-21 01:56:30
【问题描述】:

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

【问题讨论】:

    标签: java android broadcastreceiver bluetooth-lowenergy


    【解决方案1】:

    我想知道如何实现这一点

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

    private Map<String, BluetoothGatt> connectedDeviceMap; 
    

    在服务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 中删除/p>

            @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)不同的连接。

    每个连接都需要一个单独的线程吗?

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

    希望这对您有所帮助。

    【讨论】:

    • 你是在一节课上做这一切吗?我现在拥有的当前结构是回调和实际连接在另一个类中完成,即 DeviceControlActivity 具有 BluetoohLeService 的实例。如果是这样,我应该只在 DeviceControlActivity 中制作哈希图,BlueToothLeService 的每个实例都有一个单独的 bluetoohgatt。
    • 是的,我已经在Service 上完成了所有这些代码。您可以在服务中使用BluetoothGattCallbackMapMap 仅用于存储单独的 BluetoothGattCallback 对象。如果您需要,您可以在班级之间分享Map。 Android Service 没有很多实例。如果Service 正在运行并且您再次启动该服务,系统将不会再次启动Service,它只会调用onStartCommand()
    • 好的,你的意思是把哈希图存储在服务中,服务的单个实例可以处理所有设备。在发送广播以更新我的活动时,我是否可以通过意图来区分设备。
    • 发送设备地址到Broadcast Intent
    • 好的,我会尝试这些建议。感谢您的回复 :) 顺便说一句,我目前在该网站上的声誉禁止我支持您的回答(至少它没有显示在此处,即使它说已记录)
    【解决方案2】:

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

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

    【讨论】:

    • 很高兴听到我的回答对您有所帮助。
    猜你喜欢
    • 2021-11-11
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 2016-05-25
    • 2020-02-06
    • 2014-10-20
    • 1970-01-01
    相关资源
    最近更新 更多