didDiscoverCharacteristics не вызывается при использовании CoreBluetooth из Java через JNI - PullRequest
1 голос
/ 14 июня 2019

Я реализую интерфейс Java для Bluetooth Low Energy на MacOS. Мы хотим позвонить в CoreBluetooth API через JNI. Я могу сканировать устройства и заполнять службы, но не могу заставить работать характеристики, потому что didDiscoverCharacteristics, похоже, не вызывается.

При запуске в качестве исполняемого файла устройства могут сканироваться, подключаться к ним, а их услуги / характеристики заполняются и печатаются на C ++. Затем приложение создается в виде динамической библиотеки и может быть загружено в Java. В Java устройство сканируется и успешно подключается, и его службы могут быть обнаружены. Но характеристики никогда не обнаруживаются при вызове из Java.

Вот поток обслуживающего персонала с некоторыми лишними частями, оставленными для ясности:

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];
}

Цель-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)
}

Я пытался установить массив CBServices в Macable только тогда, когда Swiftable обнаружил все службы и характеристики. Я попытался реализовать «посредника» между Macable и Swiftable, где каждый раз, когда PerifheralDelegate Swiftable обнаруживает службы или характеристики для службы, он обновляет список служб Middleman. И снова, все работает как исполняемый файл, но не при использовании .dylib в Java.

Мне интересно, как заставить любой из слоев C ++, Obj-C ++ или Swift ждать, пока Swift не вызовет функцию didDiscoverCharacteristics. Если я использую цикл while для ожидания признаков, основной поток блокируется, и моя программа работает вечно, ожидая обнаружения признаков, которое никогда не происходит. И если я вынуждаю мою программу спать, поток, по-видимому, будет прерван при использовании .dylib в Java.

Мне кажется, что логика обнаружения устройств и обслуживающего персонала такая же, как ожидание обнаружения характеристики, но только первые два работают правильно.

Основываясь на этой библиотеке JS , я знаю, что можно реализовать API для CoreBluetooth на неродном языке.

ОБНОВЛЕНИЕ: Это проблема с Java. Наше приложение использовало Java 8 для общения с JNI. Обновление до Java 9 полностью решило проблему без каких-либо изменений на стороне Swift.

Ответы [ 2 ]

0 голосов
/ 15 июня 2019

JNI в Java 8 может быть несовместим с тем, как CoreBluetooth обрабатывает потоки. Вы можете решить эту проблему, используя JDK 9 вместо 8.

0 голосов
/ 14 июня 2019

CoreBluetooth ведет себя так, когда не удается сохранить ссылку на соответствующий объект. Убедитесь, что вы сохраняете долговременные ссылки на периферийные устройства, службы и характеристики, которые вас интересуют, на время существования диалога BLE.

...