Android BLE - 同时连接多个设备

9
我正在开发一个连接到BLE设备并读取Gatt服务和Gatt特征的Android应用程序。我使用了Android开发网站上的BluetoothLeGatt样例项目作为参考。
到目前为止,我能够以编程方式连接到设备(我记下了设备的地址以便这样做),并通过记下服务和特征的UUID来过滤出我想要读取的特定Gatt服务和该服务的特定特征。谷歌提供的示例还会在我的BLE设备向我的Android应用程序发送消息时进行更新。总体而言,我在这方面没有任何问题。
但是,在进一步了解GATT之后,我发现可以通过单个Android应用程序连接到多个BLE设备(所有从设备或服务器-发送数据的设备),并作为主设备或客户端(接收所述数据)使用。因此,我尝试拥有2个BLE设备(不同的地址),记录它们的地址,然后当应用程序看到这两个地址正在运行时,尝试连接到它们。
在代码中,当我看到我的2个BLE设备时,我调用此函数:
private void connectToDevice(){

    mDeviceName = deviceList.get(currentIndex).getName();
    mDeviceAddress = deviceList.get(currentIndex).getAddress();

    Log.e(TAG, "connecting to device name = " + mDeviceName);

    mBluetoothLeService.connect(mDeviceAddress);
}

currentIndex 最初设置为零。当我成功连接后,我执行以下操作:

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            Log.e(TAG, "connected");
            mConnected = true;

            if(currentIndex < deviceList.size()-1) currentIndex ++;
            connectToDevice();

        } 
    }
};

我要检查一下是否还有设备可以连接到我的deviceList,如果有,就增加我的计数器并连接,直到我用完列表中的所有设备。

然而,使用这种方法似乎没有任何成功。

请注意,在我的设备之间切换连接(轮询)不是一个选项。当我有很多设备并且重要的是及时获取它们的消息而没有延迟时,这将成为一个问题。因此,我必须与我的设备保持实时连接。

有人尝试在Android上连接多个BLE设备吗?我不确定如何继续。


是的,你可以这样做,我使用一个简单的循环来实现。我的做法是,首先扫描设备,一旦找到它们,就将其放入一个ArrayList中,并调用此连接方法。为了成功建立连接,您还需要一个锁定和等待机制,因为您希望在第一个连接之后尝试建立第二个连接。 - Gautam
@Gautam你介意发布使之工作的代码吗?我很感激关于这个主题的任何线索。 - Razgriz
3个回答

4

的确,您可以从Android设备连接到多个外围设备。但是,这将使您的代码变得更加复杂,因为您需要管理每个连接和响应。

对于每个连接,您都需要实现一个具有其回调函数BluetoothGatt。我几个月前进行了一项虚拟测试,并且正如我所说,它运行良好,我能够连接到不同的外围设备。然而,如果您链接许多命令,则似乎存在一些重叠问题,描述在此线程中。


你是否还保留着几个月前的代码?老实说,我只是等待来自我的设备的消息,实际上我还没有必要发送消息,所以我不必担心命令的链接。 - Razgriz
很遗憾,这只是一个工作项目的快速PoC。一旦我测试并证明了它的可行性,由于它的简单性,它就直接被丢弃了。 - GoRoS
那就真倒霉了。请问您是否记得,您连接每个设备时是使用单独的“BluetoothLeService”,还是仅使用多个BluetoothGatt并单独处理它们的回调? - Razgriz
当然,我为每个连接开发了多个BluetoothGatt实例,并单独处理它们的回调。 - GoRoS
非常感谢。我很可能在这里分享我的答案,一旦它能够正常工作。 - Razgriz
我尝试使用多个连接、处理程序和回调来同时连接我的两个设备。然而,它似乎不起作用。我在这里发布了一个新的问题:http://stackoverflow.com/questions/35406168/android-ble-connecting-to-multiple-devices-seem-to-fail-and-gatt-response-is-t,如果您能在那里查看我的代码,那将会很有帮助。谢谢! - Razgriz

1

如所请求,以下是相关代码:(此处ArrayList包含找到的外围设备)

for(int i=0;i< Utility.selectedDeviceList.size();i++) {
            Log.d(Utility.TAG,"state"+ Utility.selectedDeviceList.get(i).getmConnectionState());
            if (Utility.selectedDeviceList.get(i).getmConnectionState() != Utility.CONNECTED) {
                Log.d(Utility.TAG,"Connecting LeSerive::" + Utility.selectedDeviceList.get(i).getAddress());
                Utility.mBluetoothLeService.connect(i, Utility.selectedDeviceList.get(i).getAddress());
            }

        }

这个 for 循环是可运行接口的一部分,它在一个拥有 looper 的 handler 内被调用。
public void run() {
    Looper.prepare();
    Looper mLooper = Looper.myLooper();
    Log.d(Utility.TAG,"BLE Thread Started::");
    mHandler = new Handler(mLooper) {

        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case Utility.BLE_SYNC:
                    Log.d(Utility.TAG,"BLE Sync Connecting::");
                    mHandler.post(SynState);
                    break;
       }
    };
    Looper.loop();
}

我使用这种方法是因为在外设之间有大量的通信来发送和接收数据。
这是一个位于服务内部的连接方法:
public boolean connect(int tag,final String address) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(Utility.TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }

    Utility.selectedDeviceList.get(tag).setmConnectionState(Utility.CONNECTING);

    if( Utility.selectedDeviceList.get(tag).getmBluetoothGatt()==null){
        Log.w(Utility.TAG, "new connect :: "+ Utility.selectedDeviceList.get(tag).getAddress());

        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(Utility.TAG, "Device not found.  Unable to connect.");
            return false;
        }
        try {
            Utility.selectedDeviceList.get(tag).setmBluetoothGatt(device.connectGatt(this, false, mGattCallback));
        }
        catch (Exception e)
        {
            e.printStackTrace();
            Log.d(Utility.TAG,"ConnectGatt exception caught");
        }
    }

    return true;
}

这是mGattCallBack:
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.d(Utility.TAG, "onServicesDiscovered");

    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {


    }
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        Log.d(Utility.TAG,">>onCharacteristicWrite");

    }
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {

    }
};

希望这能为您澄清一些问题。

我尝试使用多个连接、处理程序和回调来同时连接我的两个设备。然而,它似乎不起作用。我在这里发布了一个新的问题:http://stackoverflow.com/questions/35406168/android-ble-connecting-to-multiple-devices-seem-to-fail-and-gatt-response-is-t,如果您能在那里查看我的代码,那将会很有帮助。谢谢! - Razgriz

0

可以同时连接多个设备。根据我的经验,它的稳定性相当不错,您可以连接的设备数量(稳定)取决于您的硬件。我发现最好的做法(对我来说)是为扫描部分创建一个单独的服务,并为每个蓝牙连接创建一个服务。重要的是不要使用绑定服务,因为绑定到它时连接的终止不稳定。 使用这种模式,您可以轻松控制连接。要将数据传输出您的服务,可以使用广播接收器,例如,如果您想在主活动中显示数据。连接的终止非常重要,因此请停止服务并在onDestroy中调用。

mConnectedGatt.disconnect();
ble_device=null;

对于扫描部分,我使用了一个字符串列表,保存了所有我想要查找的MAC地址。当我找到一个设备时,我会从列表中删除它,如果列表为空,则停止扫描服务。为了传输我找到的设备,我使用了广播接收器并将其发送到我的主Activity。然后我将其传输到正确的服务。 希望这可以帮助到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接