Skip to content

patlux/react-native-bluetooth-state-manager

Repository files navigation

react-native-bluetooth-state-manager

npm version

The only purpose of this library is to manage the Bluetooth state. Not more, not less.

If you need further functionality like connecting and communicating with a device, please look at react-native-ble-plx.

Table Of Contents

Installation

Requires react-native >=0.75. See also the requirements of react-native-nitro-modules.

bun add react-native-nitro-modules react-native-bluetooth-state-manager
cd ios && bunx pod-install

# replace bun with npm/yarn/pnpm and bunx with npx

Setup

import { BluetoothStateManager } from "react-native-bluetooth-state-manager";

iOS

You must provide a short description of why you need access to Bluetooth in your app. Otherwise, your app will crash when requesting Bluetooth access:

This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSBluetoothAlwaysUsageDescription key with a string value explaining to the user how the app uses this data.

See: https://developer.apple.com/documentation/bundleresources/information_property_list/nsbluetoothalwaysusagedescription

For expo add the following to your app.json/app.config.js/app.config.ts:

{
  "ios": {
    "infoPlist": {
      "NSBluetoothAlwaysUsageDescription": "Your reason to use bluetooth"
    }
  }
}

Important: The first attempt to check the Bluetooth state will prompt the user for permission to access Bluetooth.

Android

To use requestToEnable() and requestToDisable() on Android, you have to add the BLUETOOTH_CONNECT permission to your AndroidManifest.xml:

  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
  </manifest>

BLUETOOTH_CONNECT is a runtime permission, which means you must ask the user at runtime for permission. For that, we recommend react-native-permissions.

Usage

import {
  useBluetoothState,
  BluetoothStateManager,
  BluetoothState,
} from "react-native-bluetooth-state-manager";

// Get bluetooth state

// hook
const bluetoothState = useBluetoothState();
// synchronous
const bluetoothState = BluetoothStateManager.getStateSync();
// asynchronous
const bluetoothState = await BluetoothStateManager.getState();
// Event listener
const [bluetoothState, setBluetoothState] = useState<BluetoothState>();
useEffect(() => {
  const remove = BluetoothStateManager.addListener((state) => {
    setBluetoothState(state);
  });
  return remove;
}, []);

// Open settings page
await BluetoothStateManager.openSettings();

// Android only

// Ask user to enable bluetooth
await BluetoothStateManager.requestToEnable();

// Ask user to disable bluetooth
await BluetoothStateManager.requestToDisable();

API

An example is under example/App.tsx

Method Return Type OS Description
useBluetoothState(enabled: boolean = true) BluetoothState Android, iOS Hook that returns the current state of the bluetooth service.
getState() Promise<BluetoothState> Android, iOS Returns the current state of the bluetooth service.
getStateSync() BluetoothState Android, iOS Returns the current state synchronous of the bluetooth service.
addListener(listener, emitCurrentState) Subscription Android, iOS Listen for bluetooth state changes.
openSettings() Promise<null> Android, iOS Opens the bluetooth settings. Please see below for more details.
requestToEnable() Promise<void> Android Show a dialog that allows the user to turn on Bluetooth.
requestToDisable() Promise<void> Android Show a dialog that allows the user to turn off Bluetooth.

useBluetoothState(enabled: boolean = true)

Hook that returns the current state of the bluetooth service.

import { useBluetoothState } from "react-native-bluetooth-state-manager";

const enabled = true; // default true
const bluetoothState = useBluetoothState(enabled);
switch (bluetoothState) {
  case "Unknown":
  case "Resetting":
  case "Unsupported":
  case "Unauthorized":
  case "PoweredOff":
  case "PoweredOn":
  default:
    break;
}

getState()

Returns the current state of the bluetooth service.

import { BluetoothStateManager } from "react-native-bluetooth-state-manager";
const bluetoothState = await BluetoothStateManager.getState();
switch (bluetoothState) {
  case "Unknown":
  case "Resetting":
  case "Unsupported":
  case "Unauthorized":
  case "PoweredOff":
  case "PoweredOn":
  default:
    break;
}

getStateSync()

Returns the current state synchronous of the bluetooth service.

import { BluetoothStateManager } from "react-native-bluetooth-state-manager";
const bluetoothState = BluetoothStateManager.getStateSync();
switch (bluetoothState) {
  case "Unknown":
  case "Resetting":
  case "Unsupported":
  case "Unauthorized":
  case "PoweredOff":
  case "PoweredOn":
  default:
    break;
}

addListener(listener, emitCurrentState)

Listen for bluetooth state changes.

import { BluetoothStateManager } from "react-native-bluetooth-state-manager";
BluetoothStateManager.addListener((bluetoothState) => {
  // do something...
}, true /*=emitCurrentState*/);

openSettings()

Android

Opens the bluetooth settings.

Tested:

  • Android 6.0.1 (Huawei P8 Lite ALE-L21)
  • Android 7.1.1 (Galaxy J5 2016)
  • Android 8.0 (Galaxy S8+ SM-G955f)
iOS

Opens the settings page of the app. Please see here.

BluetoothStateManager.openSettings();

requestToEnable()

Show a dialog that allows the user to turn on Bluetooth. More here: Android documentation.

  • This function is only available on Android.
try {
  await BluetoothStateManager.requestToEnable();
} catch (error) {
  // Failed
}

requestToDisable()

Show a dialog that allows the user to turn off Bluetooth.

  • This function is only available on Android.
try {
  await BluetoothStateManager.requestToDisable();
} catch (error) {
  // Failed
}

Why?

Why not just use react-native-ble-plx?

Because it's too bloated for my needs.

In several of my projects, I've had to integrate various third-party SDKs that communicate with different Bluetooth devices on the native side. The only functionality I needed on the JavaScript side was checking whether Bluetooth was enabled before starting the third-party SDK.