MacOSでBluetooth Low Energy用のJavaインターフェースを実装しています。JNIを介してCoreBluetooth APIを呼び出します。デバイスをスキャンしてサービスに入力することはできますが、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];
}
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)
}
Swiftableがすべてのサービスと特性を発見した場合にのみ、MacableでCBServicesの配列を設定してみました。MacableとSwiftableの間に「ミドルマン」を実装してみました。SwiftableのPeripheralDelegateがサービスまたはサービスの特性を検出するたびに、ミドルマンのサービスのリストが更新されます。また、すべてが実行可能ファイルとして機能しますが、Javaで.dylibを使用する場合は機能しません。
「didDiscoverCharacteristics」関数がSwiftによって呼び出されるまで、C ++、Obj-C ++、またはSwiftレイヤーを強制的に待機させる方法を知りたいのですが。whileループを使用して特性を待機すると、メインスレッドがブロックされ、プログラムは永久に実行され、決して発生しない特性の検出を待機します。また、プログラムを強制的にスリープさせると、Javaで.dylibを使用するときにスレッドが放棄されたように見えます。
デバイスとサービス人口を検出するロジックは、特徴的な検出を待つのと同じであるように見えますが、最初の2つだけが正しく機能しています。
このJSライブラリに基づいて、CoreBluetoothのAPIを非ネイティブ言語で実装できることを知っています。
更新:これはJavaの問題でした。私たちのアプリはJava 8を使用してJNIと通信していました。Java 9に更新すると、Swift側で変更を加える必要なく、問題が完全に解決されました。
Java 8のJNIは、CoreBluetoothがスレッドを処理する方法と互換性がない場合があります。この問題は、8ではなくJDK 9を使用して解決できます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加