{"id":11760,"library":"react-native-ble-plx","title":"React Native BLE Plx","description":"react-native-ble-plx is a comprehensive React Native library providing a low-level API for interacting with Bluetooth Low Energy (BLE) devices on both iOS and Android platforms. The current stable version is 3.5.1, with recent releases indicating an active development and maintenance cadence addressing bugs and improvements. It supports core BLE functionalities such as observing the Bluetooth adapter state, scanning for devices, connecting to peripherals, discovering services and characteristics, reading/writing characteristic values, observing notifications/indications, reading RSSI, and negotiating MTU. A key differentiator is its inclusion of an Expo config plugin for easier integration into managed Expo workflows (requiring prebuilding). The library explicitly does not support Bluetooth Classic, inter-phone BLE communication (peripheral mode), device bonding, or beacon technologies. It is built to provide robust control over BLE interactions in React Native applications.","status":"active","version":"3.5.1","language":"javascript","source_language":"en","source_url":"https://github.com/dotintent/react-native-ble-plx","tags":["javascript","react-native","ios","android","React","Native","Bluetooth","Low","Energy","typescript"],"install":[{"cmd":"npm install react-native-ble-plx","lang":"bash","label":"npm"},{"cmd":"yarn add react-native-ble-plx","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-native-ble-plx","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency, core React framework.","package":"react","optional":false},{"reason":"Peer dependency, core React Native framework.","package":"react-native","optional":false}],"imports":[{"note":"The primary class for managing BLE operations. CommonJS `require` is generally discouraged in modern React Native projects due to ESM prevalence.","wrong":"const BleManager = require('react-native-ble-plx').BleManager;","symbol":"BleManager","correct":"import { BleManager } from 'react-native-ble-plx';"},{"note":"Used to access and monitor the current Bluetooth adapter state (e.g., poweredOn, poweredOff). The enum is named `State`, not `BluetoothState`.","wrong":"import { BluetoothState } from 'react-native-ble-plx';","symbol":"State","correct":"import { State } from 'react-native-ble-plx';"},{"note":"Primarily used as a TypeScript type for device objects returned by scan and connection methods. While it can be imported as a value, it's typically used for type annotations.","wrong":"import { Device } from 'react-native-ble-plx';","symbol":"Device","correct":"import type { Device } from 'react-native-ble-plx';"},{"note":"Primarily used as a TypeScript type for characteristic objects. Similar to `Device`, it's generally imported as a type.","wrong":"import { Characteristic } from 'react-native-ble-plx';","symbol":"Characteristic","correct":"import type { Characteristic } from 'react-native-ble-plx';"}],"quickstart":{"code":"import { BleManager, State } from 'react-native-ble-plx';\nimport { PermissionsAndroid, Platform } from 'react-native';\n\nconst manager = new BleManager();\n\nasync function requestBluetoothPermissions() {\n  if (Platform.OS === 'ios') {\n    return true; // iOS handles permissions differently, usually in Info.plist\n  }\n\n  if (Platform.OS === 'android') {\n    const apiLevel = Platform.Version;\n    if (apiLevel < 31) { // Android 11 (API 30) and below\n      const granted = await PermissionsAndroid.request(\n        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,\n        {\n          title: 'Location Permission',\n          message: 'Bluetooth Low Energy requires Location Permission',\n          buttonNeutral: 'Ask Me Later',\n          buttonNegative: 'Cancel',\n          buttonPositive: 'OK',\n        }\n      );\n      return granted === PermissionsAndroid.RESULTS.GRANTED;\n    } else { // Android 12 (API 31) and above\n      const granted = await PermissionsAndroid.requestMultiple([\n        PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,\n        PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,\n        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,\n      ]);\n      return (\n        granted['android.permission.BLUETOOTH_SCAN'] === PermissionsAndroid.RESULTS.GRANTED &&\n        granted['android.permission.BLUETOOTH_CONNECT'] === PermissionsAndroid.RESULTS.GRANTED &&\n        granted['android.permission.ACCESS_FINE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED\n      );\n    }\n  }\n  return false;\n}\n\nexport const scanForDevices = async () => {\n  const hasPermission = await requestBluetoothPermissions();\n  if (!hasPermission) {\n    console.log('Bluetooth permissions not granted.');\n    return;\n  }\n\n  const subscription = manager.onStateChange((state) => {\n    if (state === State.PoweredOn) {\n      console.log('Bluetooth is powered on, starting scan...');\n      manager.startDeviceScan(null, { allowDuplicates: false }, (error, device) => {\n        if (error) {\n          console.error('Scan error:', error);\n          return;\n        }\n        if (device) {\n          console.log('Found device:', device.name || device.id);\n          // Example: Stop scan after finding one device\n          manager.stopDeviceScan();\n          // subscription.remove(); // Unsubscribe from state changes\n        }\n      });\n      subscription.remove(); // Remove state change listener after successful scan initiation\n    } else {\n      console.log('Bluetooth state:', state);\n    }\n  }, true);\n};\n\n// To stop scanning, typically called after a timeout or finding a device\n// manager.stopDeviceScan();\n\n// Don't forget to destroy the manager when your component unmounts or app closes\n// manager.destroy();","lang":"typescript","description":"Initializes the BleManager, requests necessary Bluetooth permissions for Android, monitors Bluetooth adapter state, and performs a device scan, logging found devices. It also demonstrates how to handle state changes and stop scanning."},"warnings":[{"fix":"Ensure all calls to `destroyClient`, `cancelTransaction`, `setLogLevel`, `startDeviceScan`, and `stopDeviceScan` are `await`ed or have `.then().catch()` handlers.","message":"In version 3.2.0, several methods (`destroyClient`, `cancelTransaction`, `setLogLevel`, `startDeviceScan`, `stopDeviceScan`) were changed to return Promises. Previously, these might have been synchronous or returned void. Existing code that does not await these calls or handle their new Promise return type will break.","severity":"breaking","affected_versions":">=3.2.0"},{"fix":"Thoroughly test your application when upgrading from v2.x to v3.0.0+. Pay attention to Bluetooth operations, especially on iOS 16, and review any direct interaction with native modules if custom bridges are in use.","message":"Major version 3.0.0 involved significant internal updates, including `MultiplatformBleAdapter` to 0.2.0, RN bridge config, and dependency updates, alongside fixes for iOS 16 bugs. While not explicitly detailed as breaking, such changes often introduce subtle incompatibilities.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure your application design accounts for a single `BleManager` instance. If you were creating multiple instances for different purposes, you might need to refactor to use a single manager and manage its state and operations carefully.","message":"As of version 3.4.0, `BleManager` is implemented as a singleton. While this aims to simplify its usage in React components/hooks, it changes the underlying behavior. If you were instantiating `BleManager` multiple times and expecting distinct instances, this will no longer be the case.","severity":"gotcha","affected_versions":">=3.4.0"},{"fix":"For Expo projects, add `react-native-ble-plx` to the `plugins` array in `app.json` or `app.config.js` and run `npx expo prebuild` before building or running your app on a device or simulator.","message":"Using `react-native-ble-plx` with Expo requires the application to be prebuilt (`npx expo prebuild`). It is not compatible with 'Expo Go' because it relies on custom native code. Failing to prebuild will result in runtime errors.","severity":"gotcha","affected_versions":">=3.1.0"},{"fix":"Implement robust runtime permission requests for Android and ensure `Info.plist` is correctly configured for iOS. Lack of permissions will lead to scanning or connection failures without clear error messages from the library.","message":"Proper Bluetooth permissions are crucial for the library to function. On Android, this involves `ACCESS_FINE_LOCATION` (for Android 11 and below), and `BLUETOOTH_SCAN`, `BLUETOOTH_CONNECT`, `ACCESS_FINE_LOCATION` (for Android 12/API 31 and above). iOS requires entries in `Info.plist` for `NSBluetoothAlwaysUsageDescription` and `NSBluetoothPeripheralUsageDescription`.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Upgrade to `react-native-ble-plx@3.5.1` or newer. Implement robust error handling and null checks around device, service, and characteristic access after discovery. Ensure `BleManager.destroy()` is called when no longer needed.","cause":"Attempts to access properties on a null object, often due to race conditions or incorrect cleanup during service/characteristic discovery. Fixed in v3.5.1 for specific cases.","error":"TypeError: Cannot read properties of null (reading 'getDeviceID') OR Service.getDeviceID()' on a null object reference"},{"fix":"Upgrade to `react-native-ble-plx@3.5.1` or newer to resolve this Android-specific crash.","cause":"A specific bug on Android where internal promise rejections were sometimes made with null arguments, leading to a crash. Fixed in v3.5.1.","error":"Promise.reject crash with null arguments"},{"fix":"For Expo projects, ensure you are using a custom development client or a prebuilt standalone app. Add the config plugin to `app.json` and run `npx expo prebuild`.","cause":"Attempting to run a project using `react-native-ble-plx` in the 'Expo Go' app.","error":"Error: You cannot use this package in Expo Go. It requires custom native code."},{"fix":"Verify that all necessary Android permissions (`ACCESS_FINE_LOCATION`, `BLUETOOTH_SCAN`, `BLUETOOTH_CONNECT` as per API level) are requested and granted at runtime. For iOS, confirm `NSBluetoothAlwaysUsageDescription` and `NSBluetoothPeripheralUsageDescription` are present and correctly filled in `Info.plist`.","cause":"Missing or improperly granted Bluetooth permissions on Android or incorrect `Info.plist` entries on iOS.","error":"Bluetooth scan fails or no devices found, despite Bluetooth being on."},{"fix":"Upgrade to `react-native-ble-plx@3.2.1` or newer to benefit from fixes related to `this` context and Fast Refresh on Android.","cause":"Older versions (prior to 3.2.1) had issues with `this` context for some methods after React Native Fast Refresh on Android.","error":"TypeError: Cannot read properties of undefined (reading 'callMethod') or 'this' context issues on Android."}],"ecosystem":"npm"}