From 91a4d0089d4a3125987cc5d4cb0934bb7c004ffd Mon Sep 17 00:00:00 2001 From: Emanuele Toffolon Date: Thu, 21 Nov 2024 10:59:50 +0100 Subject: [PATCH] feat(android): Add getBondedDevices method to retrieve bonded devices on Android (#716) --- README.md | 15 ++++++++++++ .../plugins/bluetoothle/BluetoothLe.kt | 24 +++++++++++++++++++ ios/Plugin/Plugin.m | 1 + ios/Plugin/Plugin.swift | 4 ++++ src/bleClient.spec.ts | 3 +++ src/bleClient.ts | 14 +++++++++++ src/definitions.ts | 1 + src/web.ts | 4 ++++ 8 files changed, 66 insertions(+) diff --git a/README.md b/README.md index 96a892ea..004c4342 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ Below is an index of all the methods available. - [`requestLEScan(...)`](#requestlescan) - [`stopLEScan()`](#stoplescan) - [`getDevices(...)`](#getdevices) +- [`getBondedDevices()`](#getbondeddevices) - [`getConnectedDevices(...)`](#getconnecteddevices) - [`connect(...)`](#connect) - [`createBond(...)`](#createbond) @@ -588,6 +589,20 @@ On Android, you can directly connect to the device with the deviceId. --- +### getBondedDevices() + +```typescript +getBondedDevices() => Promise +``` + +Get a list of currently bonded devices. +Only available on **Android**. +Uses [getBondedDevices]() on Android + +**Returns:** Promise<BleDevice[]> + +--- + ### getConnectedDevices(...) ```typescript diff --git a/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/BluetoothLe.kt b/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/BluetoothLe.kt index a0fb4734..87e589a5 100644 --- a/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/BluetoothLe.kt +++ b/android/src/main/java/com/capacitorjs/community/plugins/bluetoothle/BluetoothLe.kt @@ -434,6 +434,30 @@ class BluetoothLe : Plugin() { call.resolve(result) } + @PluginMethod + fun getBondedDevices(call: PluginCall) { + assertBluetoothAdapter(call) ?: return + + val bluetoothManager = activity.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + val bluetoothAdapter = bluetoothManager.adapter + + if (bluetoothAdapter == null) { + call.reject("Bluetooth is not supported on this device") + return + } + + val bondedDevices = bluetoothAdapter.bondedDevices + val bleDevices = JSArray() + + bondedDevices.forEach { device -> + bleDevices.put(getBleDevice(device)) + } + + val result = JSObject() + result.put("devices", bleDevices) + call.resolve(result) + } + @PluginMethod fun connect(call: PluginCall) { val device = getOrCreateDevice(call) ?: return diff --git a/ios/Plugin/Plugin.m b/ios/Plugin/Plugin.m index 8fe596ae..c24d6fb4 100644 --- a/ios/Plugin/Plugin.m +++ b/ios/Plugin/Plugin.m @@ -25,6 +25,7 @@ CAP_PLUGIN_METHOD(connect, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(createBond, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(isBonded, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(getBondedDevices, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(disconnect, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getServices, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(getMtu, CAPPluginReturnPromise); diff --git a/ios/Plugin/Plugin.swift b/ios/Plugin/Plugin.swift index f23114be..bea55270 100644 --- a/ios/Plugin/Plugin.swift +++ b/ios/Plugin/Plugin.swift @@ -248,6 +248,10 @@ public class BluetoothLe: CAPPlugin { call.unavailable("isBonded is not available on iOS.") } + @objc func getBondedDevices(_ call: CAPPluginCall) { + call.unavailable("getBondedDevices is not available on iOS.") + } + @objc func disconnect(_ call: CAPPluginCall) { guard self.getDeviceManager(call) != nil else { return } guard let device = self.getDevice(call, checkConnection: false) else { return } diff --git a/src/bleClient.spec.ts b/src/bleClient.spec.ts index 5a7cf77f..24ca8342 100644 --- a/src/bleClient.spec.ts +++ b/src/bleClient.spec.ts @@ -35,6 +35,9 @@ jest.mock('./plugin', () => { getConnectedDevices: jest.fn(() => { return Promise.resolve({ devices: [] }); }), + getBondeddDevices: jest.fn(() => { + return Promise.resolve({ devices: [] }); + }), connect: jest.fn(), createBond: jest.fn(), isBonded: jest.fn(), diff --git a/src/bleClient.ts b/src/bleClient.ts index 34de6b06..ddd0012d 100644 --- a/src/bleClient.ts +++ b/src/bleClient.ts @@ -129,6 +129,13 @@ export interface BleClientInterface { */ getDevices(deviceIds: string[]): Promise; + /** + * Get a list of currently bonded devices. + * Only available on **Android**. + * Uses [getBondedDevices](https://developer.android.com/reference/android/bluetooth/BluetoothAdapter#getBondedDevices()) on Android + */ + getBondedDevices(): Promise; + /** * Get a list of currently connected devices. * Uses [retrieveConnectedPeripherals](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1518924-retrieveconnectedperipherals) on iOS, @@ -460,6 +467,13 @@ class BleClientClass implements BleClientInterface { }); } + async getBondedDevices(): Promise { + return this.queue(async () => { + const result = await BluetoothLe.getBondedDevices(); + return result.devices; + }); + } + async connect(deviceId: string, onDisconnect?: (deviceId: string) => void, options?: TimeoutOptions): Promise { await this.queue(async () => { if (onDisconnect) { diff --git a/src/definitions.ts b/src/definitions.ts index ce980a21..a9e45f41 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -289,6 +289,7 @@ export interface BluetoothLePlugin { stopLEScan(): Promise; getDevices(options: GetDevicesOptions): Promise; getConnectedDevices(options: GetConnectedDevicesOptions): Promise; + getBondedDevices(): Promise; addListener( eventName: 'onEnabledChanged', listenerFunc: (result: BooleanResult) => void diff --git a/src/web.ts b/src/web.ts index 66141019..011295c5 100644 --- a/src/web.ts +++ b/src/web.ts @@ -174,6 +174,10 @@ export class BluetoothLeWeb extends WebPlugin implements BluetoothLePlugin { return { devices: bleDevices }; } + async getBondedDevices(): Promise { + return {} as Promise; + } + async connect(options: DeviceIdOptions & TimeoutOptions): Promise { const device = this.getDeviceFromMap(options.deviceId); device.removeEventListener('gattserverdisconnected', this.onDisconnectedCallback);