How can I list connected devices?
Question
How can I list the connected devices?
Steps:
- I start the device scan
- I find the device by name and connect to it to check the services and characteristics
- I make some changes on the app and run it again
- This time the scan doesn't include my device, as it says on the introduction: "However when device is connected it won't broadcast and needs to be disconnected from central to be scanned again."
- Ok, so how can I find the connected device so I can disconnect it, or use it?
I tried
let connectedDevices = await manager.connectedDevices(null) or () - gives an error - Attempt to invoke interface method 'int.com.facebook.react.bridge.ReadableArray.size()' on a null object reference
let connectedDevices = await manager.connectedDevices([]) - gives an empty array
The connectedDevices method needs a serviceUUIDs parameter but how can I get the connected devices regardless of their serviceUUIDs?
I'm still trying to get this method working but it doesn't give any results:
let connectedDevices = await manager.connectedDevices([config.serviceUUID]);
There is one device connected with that serviceUUID but the result is allways an empty array.
Is this a Bug?
As I know the connectedDeivces func will only retrieve devices which are connnected to the manager not the android/iOS devices. So if you want to retrieve bonded peripherals, you have to use react-native-ble-manager and it would only work on android.
@nbastoWM Did u ever solve this? I'm getting the same error "Attempt to invoke interface method 'int com.facebook.react.bridge.ReadableArray.size()' on a null object reference". However only on android, on iOS it works fine.
@nbastoWM
I was just having this problem, and the issue was that the serviceUUIDs var I was passing into connectedDevices was null. That must be the null that the error is referring to.
It was happening because I was assigning serviceUUIDs as a class variable in the class definition, then calling it from a class method. Instead I needed to assign it as this.serviceUUIDs in a class init/constructor function that is called first.
My code works fine in iOS and older Android versions, so there must be something new about the way classes are interpreted.
This is still an issue: I specifically run into it during development all the time with the following set up on Android:
- use react-native-ble-plx to discover and connect to my BLE device.
- As a developer using Metro for react native, press 'r' to reload my app.
- Now the app has lost the connection state normally returned by
connectedDevices(). I get 0 devices listed even though my BLE device is happily still connected to my Android phone.
I can verify this is the problem because I use this (unacceptable for production) quick workaround: if you disable and enable Bluetooth on your Android phone, that will disconnect from your BLE hardware, and now your app state will match the hardware.
While dev mode is the easiest to reproduce this in, it's relatively easy to see how this would happen in production: literally any crash in your app or killing of your app by a 3rd party service or Android OS will cause this bad state to exist
Until this issue is resolved I have resorted to a dual- library approach: using this library and ALSO react-native-ble-manager together. This is the only solution as of December 2021 that doesn't require a user to disable and enable Bluetooth on Android.
My shim:
import BleManager from 'react-native-ble-manager'
import { NativeModules, NativeEventEmitter } from 'react-native'
const BleManagerModule = NativeModules.BleManager
// This shim replaces react-native-ble-plx's BleManager.connectedDevices because the latter does not return devices connected that
// might have been connected before the app was started (or, more likely, before the app was crashed and restarted.)
// This functionality means that we can't use the react-native-ble-plx's BleManager.connectedDevices because our connected device
// won't show up on it.
const getConnectedDeviceIds = async (serviceUUIDs) => {
const connectedPeripherals = await BleManager.getConnectedPeripherals(serviceUUIDs)
return connectedPeripherals.map(peripheral => peripheral.id)
}
export { getConnectedDeviceIds }
And an excerpt of how I use it (in my React Native provider load function):
// SHIM: Sync the PLX bleManager wearables list with the devices connected in hardware
// since the PLX bleManager doesn't return them right now.
const ids = await getConnectedDeviceIds([SILVERTREE_SERVICE_UUID])
for (id of ids){
// Sync up PLX's state with the hardware state:
const connectedDevice = await bleManager.connectToDevice(id, { refreshGatt: 'OnConnected', autoConnect: false });
}
// Now our app state should match the hardware state.
I'm excited to inform you that we've released a new version of react-native-ble-plx. Many of the concerns and bugs have been addressed in this update.
If you encounter any issues or have further suggestions, please don't hesitate to open a new issue.
@abursztynowska Is this issue resolved with new version? If it is what is solution?
@abursztynowska Could this issue potentially be re-opened? I'm facing the same issue that the plx-state isn't in sync with the (android)-device's state. I can't find any information in the documentation regarding this issue.