Java Question Get data to java from b4A using ba.raiseEventFromDifferentThread?

TurboCCC

Member
Licensed User
Hi B4A community,

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()});

Could it be only to do?
Java:
object return = ba.raiseEventFromDifferentThread...

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?

Note: I'm a newbie at all this. :)
Thanks.
 
Last edited:

TurboCCC

Member
Licensed User
Hi Erel,

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.

Thanks.
 
Last edited:

TurboCCC

Member
Licensed User
Hi Erel,

I tried a simple example with a String return:
Code:
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?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
It is probably a background thread, though you cannot know it for sure.

Worth checking.

Add:
B4X:
BA.Log("Threadid: " + Thread.currentThread().getId());
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.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
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.
 
Top