【问题标题】:Android BLE - Connecting to multiple devices at onceAndroid BLE - 一次连接到多个设备
【发布时间】:2016-05-25 09:11:34
【问题描述】:

我正在开发一个连接到 BLE 设备并读取 Gatt 服务和 Gatt 特性的 Android 应用程序。我使用了 Android Development Site 中的 BluetoothLeGatt 示例项目作为参考。

到目前为止,我能够以编程方式连接到设备(我记下了我的设备地址以便能够执行此操作)并通过记下过滤掉我想要读取的特定 Gatt 服务以及该服务的特定特征服务和特征的 UUID。每当有消息从我的 BLE 设备发送到我的 Android 应用程序时,Google 提供的示例也会更新。总的来说,我在这方面没有问题。

但是,在进一步阅读 GATT 后,我发现可以使用单个 Android 应用程序(作为主设备或客户端 - 作为接收所述数据的人)。所以我试图做的是拥有 2 个 BLE 设备(不同的地址),记下它们的地址,然后一旦应用程序看到这 2 个地址已启动并正在运行,我的应用程序就会尝试连接到它们。

在代码中,当我看到我的 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 设备?我不确定如何继续。

【问题讨论】:

  • 是的,你可以,我已经用一个简单的循环完成了。我所做的是,首先我扫描设备,一旦找到它们,我就把它放在一个数组列表中并调用这个连接方法。要成功建立连接,您还需要一个锁定和等待机制,因为您想在第一个连接之后尝试建立第二个连接。
  • @Gautam 你介意发布你的代码吗?我将不胜感激有关此主题的任何线索。

标签: android gatt bluetooth-lowenergy


【解决方案1】:

确实,您可以从您的 Android 设备连接多个peripheral。但是,这会使您的代码更加复杂,因为您需要管理每个连接和响应。

对于每个连接,您都必须使用 callbacks 实现 BluetoothGatt。几个月前我用虚拟测试对其进行了测试,正如我所说,它运行良好,我能够连接到不同的外围设备。但是,如果您链​​接许多命令,this thread 中似乎会出现一些重叠问题。

【讨论】:

  • 你会不会碰巧还有几个月前的代码?老实说,我所做的只是等待来自我的设备的消息,实际上我还不必发送消息,所以我不必担心链接命令。
  • 很遗憾,它是一个工作项目的快速 PoC,一旦我测试并证明了它,由于它的简单性,它直接被丢弃了。
  • 那我真倒霉。您还记得您是否为必须连接的每个设备使用了一个单独的BluetoothLeService 吗?还是您只是使用多个 BluetoothGatt 并单独处理它们的回调?
  • 当然,我为每个连接开发了多个 BluetoothGatt 实例并单独处理它们的回调。
  • 非常感谢。当我得到它的工作时,我很可能会在这里分享我的答案。
【解决方案2】:

这里问的是相关代码:(这里的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 循环是可运行接口的一部分,它在具有循环器的处理程序内部调用。

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) {

    }
};

希望它能为你清除一些事情

【讨论】:

  • 我尝试进行多个连接、处理程序和回调,以尝试同时连接到我的 2 台设备。但是,它似乎不起作用。我在这里发布了一个关于它的新问题:stackoverflow.com/questions/35406168/…,如果您可以在那里查看我的代码,将会有所帮助。谢谢!
【解决方案3】:

一次可以连接多个设备。以我的经验,它工作得非常稳定,您可以连接的设备数量(稳定)取决于您的硬件。我发现(对我来说)最佳实践是为扫描内容创建一个单独的服务,为每个蓝牙连接创建一个服务。重要的是不要使用绑定服务,因为绑定到它时连接的终止是不稳定的。 使用此模式,您可以轻松控制连接。要将数据传输出您的服务,您可以使用广播接收器,例如,如果您想在主要活动中显示数据。终止连接非常重要,所以停止服务并在 onDestroy 调用中

mConnectedGatt.disconnect();
ble_device=null;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多