didDiscoverCharacteristics not getting called when using CoreBluetooth from Java via JNI

Nick :

I'm implementing a Java interface for Bluetooth Low Energy on MacOS. We want to call into the CoreBluetooth API via JNI. I'm able to scan for devices and populate services, but I can't get characteristics to work because didDiscoverCharacteristics does not seem to be getting called.

When running as an executable, devices can be scanned for, connected to, and their services/characteristics populated and printed in C++. The app then gets built as a dynamic library, and can be loaded in Java. In Java, the device is scanned for and connected to successfully, and its services can be discovered. But characteristics are never discovered when called from Java.

Here is the flow of the service population, with some superfluous parts left out for clarity:

C++: BluetoothCentralNative.cpp

// tell "macable bridge" to populate services/characteristics
macableBridge.populateServices(name, UUID);
// retreive the discovered services (with characteristics populated)
vector<vector<string>> serviceData = macableBridge.getDiscoveredServices();

Objective-C++: MacableBridge.mm

void MacableBridge::populateServices(string name, string UUID) {
    NSString* nameString = [NSString stringWithCString:name.c_str() encoding:NSUTF8StringEncoding];
    NSString* uuidString = [NSString stringWithCString:UUID.c_str() encoding:NSUTF8StringEncoding];
    CBPeripheral* foundPeripheral = [macable findPeripheral:nameString deviceUUID:uuidString];
    [macable connectToDevice:foundPeripheral];
    [macable populateServices:foundPeripheral];
}

Objective-C: Macable.m

- (void) populateServices:(CBPeripheral *)device {
    [_swift populateServicesWithDevice:device];
    // sleep needs to be here to discover characteristics successfully as executable
    // but when we sleep, thread seems to die when calling this library from java
    sleep(1);
    // more on retrieval of populated services later
}

Swiftable.swift

@objc public func populateServices(device: CBPeripheral) {
    device.discoverServices(nil);
}

PeripheralDelegate.swift

// invoked when the peripheral's available services are discovered
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    print("\nServices discovered!\n")
    //middleman.gotServices(peripheral.services)    (more on this later)
    for service in peripheral.services! {
        peripheral.discoverCharacteristics(nil, for: service)
    }
}

// invoked when characteristics of a specified service are discovered
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    print("Discovered characteristics for service: \(service)")
    //middleman.gotCharacteristics(service)
}

I tried setting an array of CBServices in Macable only when Swiftable has discovered all services and characteristics. I tried implementing a "Middleman" between Macable and Swiftable, where every time Swiftable's PeripheralDelegate discovers services or characteristics for a service, it updates the Middleman's list of services. And again, everything works as an executable but not when using the .dylib in Java.

I am wondering how I can force any of the C++, Obj-C++ or Swift layers to wait until the "didDiscoverCharacteristics" function is invoked by Swift. If I use a while loop to wait for characteristics, the main thread gets blocked and my program runs forever waiting for a characteristic discovery that never happens. And if I force my program to sleep, the thread seems to be abandoned when using the .dylib in Java.

It seems to me that the logic of discovering devices and service population is the same as waiting for characteristic discovery, but only the first two are working correctly.

Based on this JS library, I know that it is possible to implement an API for CoreBluetooth in a non-native language.

UPDATE: It was an issue with Java. Our App was using Java 8 to talk to JNI. Updating to Java 9 completely solved the problem with no changes needed on the Swift side.

sid91 :

Java 8's JNI might be incompatible with the way CoreBluetooth handles threading. You can solve this issue by using JDK 9 instead of 8.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

How to prevent MediaPlayer from getting started when setPlaybackParams() is called using Java in Android Studio?

From Java

Keeping java methods called from Android JNI

From Dev

iOS CoreBluetooth : centralManager:didConnectPeripheral / didFailToConnectPeripheral: not getting called

From Java

Monitoring memory usage for a C DLL called with Java via JNI?

From Java

Getting a null byte array in java from JNI

From Dev

Can you create a new JVM in a c++ function called from java using JNI?

From Dev

Java-Program terminating early without error-message after being called from C++ via JNI

From Java

Getting text data from C++ using JNI through std::ostream into Java

From Dev

innerHTML not getting called when using getElementsByClassName

From Java

Postmapping not getting called when api called from angular to spring boot

From Java

Passing a pointer from JNI to Java using a long

From Dev

Call fortran dll from java using JNI

From Dev

Pass multiple parameters from java to c++ application via JNI

From Java

Calling into a saved java object via JNI from a different thread

From Java

How to pass null from C++ to Java via Qt JNI?

From Dev

Register callback from Java to C via JNI or JNA

From Dev

How can I invoke a Java method from Rust via JNI?

From Dev

OpenCV JNI: Java/native handling of Mat - possibility for delete getting called twice?

From Java

Getting an AmazonKinesisException Status Code: 502 when using LocalStack from Java

From Dev

Getting 404 at toRepresentation() when integrating Keycloak via REST API using JAVA

From Dev

Getting error when using clientside_callback via Java Script in Dash - Python

From Dev

Redirect URL not getting called when authenticating using Xamarin.Auth

From Dev

onOptionsItemSelected not getting called when using custom action view

From Dev

prepareForSegue is not getting called when I click on a button without using performSegueWithIdentifier

From Dev

application:continueUserActivity:restorationHandler: is not getting called when using handoff

From Java

JNI crash when called with a String argument

From Dev

How to preserve class variables accessed from JNI when using ProGuard

From Dev

CSS not getting applied when called from external stylesheet

From Dev

didSelectItemAt from collectionView not getting called when the collectionView is inside a UITableView row

Related Related

  1. 1

    How to prevent MediaPlayer from getting started when setPlaybackParams() is called using Java in Android Studio?

  2. 2

    Keeping java methods called from Android JNI

  3. 3

    iOS CoreBluetooth : centralManager:didConnectPeripheral / didFailToConnectPeripheral: not getting called

  4. 4

    Monitoring memory usage for a C DLL called with Java via JNI?

  5. 5

    Getting a null byte array in java from JNI

  6. 6

    Can you create a new JVM in a c++ function called from java using JNI?

  7. 7

    Java-Program terminating early without error-message after being called from C++ via JNI

  8. 8

    Getting text data from C++ using JNI through std::ostream into Java

  9. 9

    innerHTML not getting called when using getElementsByClassName

  10. 10

    Postmapping not getting called when api called from angular to spring boot

  11. 11

    Passing a pointer from JNI to Java using a long

  12. 12

    Call fortran dll from java using JNI

  13. 13

    Pass multiple parameters from java to c++ application via JNI

  14. 14

    Calling into a saved java object via JNI from a different thread

  15. 15

    How to pass null from C++ to Java via Qt JNI?

  16. 16

    Register callback from Java to C via JNI or JNA

  17. 17

    How can I invoke a Java method from Rust via JNI?

  18. 18

    OpenCV JNI: Java/native handling of Mat - possibility for delete getting called twice?

  19. 19

    Getting an AmazonKinesisException Status Code: 502 when using LocalStack from Java

  20. 20

    Getting 404 at toRepresentation() when integrating Keycloak via REST API using JAVA

  21. 21

    Getting error when using clientside_callback via Java Script in Dash - Python

  22. 22

    Redirect URL not getting called when authenticating using Xamarin.Auth

  23. 23

    onOptionsItemSelected not getting called when using custom action view

  24. 24

    prepareForSegue is not getting called when I click on a button without using performSegueWithIdentifier

  25. 25

    application:continueUserActivity:restorationHandler: is not getting called when using handoff

  26. 26

    JNI crash when called with a String argument

  27. 27

    How to preserve class variables accessed from JNI when using ProGuard

  28. 28

    CSS not getting applied when called from external stylesheet

  29. 29

    didSelectItemAt from collectionView not getting called when the collectionView is inside a UITableView row

HotTag

Archive