Using ba.raiseEventFromDifferentThread, I found numerous examples on how to call a B4A function from the java library and pass parameters. I'm looking for a way to get data back from my call to the B4A function. I found no example of this. Can you help?
The application is as follow: When a Central reads from a characteristic, it's expecting a return value. I'd like to call a B4A function that will return the data to be read and pass it to the java library. How can I modify this call to achieve this?
Java:
ba.raiseEventFromDifferentThread(Library.this, null, 0, eventName + "_getData", false, new Object[]{device.getAddress(), characteristic.getUuid().toString()});
One last requirement to make this practical: the return value will be an array of bytes. So how should I write this to convert my return object to an array of bytes?
1- I am not sure how to get my byte[] return value. The only syntax that seem to work is Object obj = ba.raiseEvent(...), but how do I convert to an array of bytes?
2- In your existing BlePeripheral2 library, you were using the ba.raiseEventFromDifferentThread call. I'm not exactly sure why but using the ba.raiseEvent seems to have an impact on threads that I am not familiar with. Will it causes a problem? Total newbie at this stuff.
Sub Peripheral_GetData (Characteristic As String) As String
Return "TEST"
End Sub
On the java library side, I used:
Java:
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
String s = (String) ba.raiseEvent(BlePeripheral3.this, eventName + "_getdata", new Object[]{characteristic.getUuid().toString()});
BA.Log("Response: " + s);
gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, characteristic.getValue() == null ? new byte[8] : characteristic.getValue());
}
The function Peripheral_GetData get called but the response on the java library side is always null. I read that ba.raiseEvent should not be called from a different thread. How do I know that? This is called from a a callback in the bluetooth thread. In my mind, this is a different thread. So what are my options to get something back from the B4A thread?
Add this line to the event method and also to one of the methods that are called from B4A and compare the results.
If it is indeed a background thread then you will need to use CountDownLatch to hold the background thread until the result is available. I will explain more after you check it.
You have several options:
1. Simple and a bit limited:
Let the developer build a Map with the expected input values and output values.
This is simple to implement, when you receive a read request, you check the map and return the response. Send some default response if not available.
2. More complicated and more flexible:
Something like:
Java:
@Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
String s = (String) ba.raiseEvent(BlePeripheral3.this, eventName + "_getdata", new Object[]{characteristic.getUuid().toString()});
BA.Log("Response: " + s);
BLELock lock = new BLELock();
ba.raiseEventFromDifferentThread(... send the lock)
lock.latch.await();
gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, lock.value);
}
@ShortName("BLELock")
public static class BLELock {
CountDownLatch latch = new CountDownLatch(1);
byte[] value;
public void Respond(byte[] Value) {
this.value = Value;
latch.countDown();
}
}
The developer must call Lock.Respond from this event sub.