Communication between BLE device and different and

2019-02-14 14:45发布

问题:

I'm new in Android BLE so my question may be uncorrect or naive in some way. If this is the case please explain me where I'm wrong and kindly show me the correct way to manage this scenario.

Scenario is the following: my Android app communicates with a BLE device sending commands and getting answers from device using BLE characteristics.

Sequence is:

  • Device wakes up the app (the onConnectionStateChange method is called)
  • My app writes a command in a characteristic (I call writeCharacteristic putting the command in value parameter).
  • Device sends back the answer to command to my app (the onCharacteristicChanged method is triggered and value parameter contains the answer)

After waking up the app, the device doesn't do anything until a command is sent via writeCharacteristic. The device accepts different commands.

All good so far, but recently I developed a second different app to communicate with same device.

When I run both apps on same Android phone, one app sends a command to the device and the response is received by both apps! Of course the app that didn't sent the command receives an unexpected answer and goes to an unexpected status.

Ok, knowing the problem I can modify both my apps to handle this situation, but the question is: Is this behavior normal when two apps in same device communicate with same BLE device?

Is there a way for an app to establish a communication channel with a BLE device to avoid sending answer to specific commands to any other app except the one that sent the request?

My guess is that writeCharacteristic and onNotificationChanged aren't the right functions for such kind of communication, but in this case which are the alternatives?

回答1:

The Bluetooth standard itself doesn't define anything how multiple apps would behave if both have a GATT connection to the same device. In the standard there is just one "GATT client".

Now both iOS and Android have taken one step further in a way that might seem unintuitive. Instead of only allowing one app at a time to communicate, multiple apps can be connected over the same GATT client to a device. The OS "multiplexes" the communication from/to the apps. The behaviour is that responses to read and write requests can only be seen by the app that made the request. So if you do readCharacteristic only that app will get the onCharacteristicRead callback. Notifications however will be delivered to both apps to the onCharacteristicChanged callback, since it wouldn't make any sense to send the notification to only one.

When you say that the "response" to a write request is the notification, that's not correct in terms of GATT terminology. The response to a write request is always empty per specification (or an error). If your peripheral emits a notification, then in your case that might be the "answer" according to your own logic, but it's not a response or any way related to your write request per the GATT specification. That's why Android can't (and shouldn't) send the notification to only one device.

I suggest that you simply ignore notifications you are not expecting. If you want to associate an "answer" to a write request, you can change your protocol to include a transaction id in both packets so they can be matched.

When I write "app" above, I really mean BluetoothGatt objects. You can call connectGatt twice with the same remote device in the same app, which will behave the same as if you connected from two different apps.