Skip to main content

Working with Bluetooth and NFC

1. Setting Up Bluetooth Permissions

Example: Requesting Bluetooth Permissions

import { PermissionsAndroid, Platform } from 'react-native';

const requestBluetoothPermission = async () => {
  if (Platform.OS === 'android') {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
        {
          title: 'Bluetooth Permission',
          message: 'This app needs access to Bluetooth to connect to devices',
          buttonNeutral: 'Ask Me Later',
          buttonNegative: 'Cancel',
          buttonPositive: 'OK'
        }
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        console.log('Bluetooth permission granted');
      } else {
        console.log('Bluetooth permission denied');
      }
    } catch (err) {
      console.warn(err);
    }
  }
};
Permission Android Manifest Description
ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION Required for Bluetooth scanning and device discovery on Android 6.0+
BLUETOOTH_ADMIN BLUETOOTH_ADMIN Required to enable/disable Bluetooth and discover devices
BLUETOOTH BLUETOOTH Required to use Bluetooth features (e.g., connect to devices)
Note: On Android 12+, you must also request ACCESS_FINE_LOCATION for Bluetooth scanning. This is a runtime permission that must be requested at runtime.
Warning: On Android 10 and below, ACCESS_COARSE_LOCATION is sufficient for Bluetooth scanning. However, starting from Android 11, ACCESS_FINE_LOCATION is required.

Permission Requirements Summary

  • Android 6.0+: ACCESS_FINE_LOCATION is required for Bluetooth scanning
  • Android 10 and below: ACCESS_COARSE_LOCATION is sufficient for basic scanning
  • Android 12+: ACCESS_FINE_LOCATION is required for all Bluetooth operations
  • Always include: BLUETOOTH and BLUETOOTH_ADMIN in manifest

2. Scanning for Bluetooth Devices

Example: Scan for nearby Bluetooth devices

import { BleManager } from 'react-native-ble-manager';

const manager = new BleManager();

const scanForDevices = async () => {
  try {
    await manager.startScan([], 10000); // Scan for 10 seconds
    console.log('Scanning started...');
  } catch (error) {
    console.error('Scan error:', error);
  }
};

scanForDevices();
Property Description Values
scanDuration Duration to scan for devices in milliseconds 10000
scanFilters Optional filters to apply during scan []
Note: Make sure to request Bluetooth permissions before scanning.
Warning: Scanning can drain battery quickly. Always stop scanning when done.

3. Connecting to Bluetooth Devices

Property Description Notes
bluetoothState Current state of Bluetooth adapter Can be 'unknown', 'unsupported', 'unauthorized', 'disabled', 'enabled'
isBluetoothEnabled Boolean indicating if Bluetooth is enabled Useful for checking before attempting to connect

Example: Check Bluetooth State

import { BluetoothManager } from 'react-native-bluetooth-ble';

BluetoothManager.start();
BluetoothManager.on('bluetoothState', (state) => {
  console.log('Bluetooth State:', state);
});

Example: Enable Bluetooth

import { PermissionsAndroid, Platform } from 'react-native';
import { BluetoothManager } from 'react-native-bluetooth-ble';

const requestBluetoothPermission = async () => {
  if (Platform.OS === 'android') {
    const granted = await PermissionsAndroid.request(
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      {
        title: 'Location Permission',
        message: 'This app needs access to location to scan for Bluetooth devices.',
        buttonNeutral: 'Ask Me Later',
        buttonNegative: 'Cancel',
        buttonPositive: 'OK'
      }
    );
    return granted === PermissionsAndroid.RESULTS.GRANTED;
  }
  return true;
};

const enableBluetooth = async () => {
  const hasPermission = await requestBluetoothPermission();
  if (hasPermission) {
    BluetoothManager.start();
  }
};
Note: On Android, you must request location permission to scan for Bluetooth devices. This is a requirement from Google's Play Store policy.
Warning: Bluetooth operations are asynchronous and may take time to complete. Always handle potential errors gracefully.
Method Description Return Type
start() Initializes the Bluetooth manager Promise<void>
scanForPeripherals() Starts scanning for nearby Bluetooth peripherals Promise<void>
connectToDevice(deviceId) Attempts to connect to a specific Bluetooth device Promise<void>
disconnectFromDevice(deviceId) Disconnects from a specific Bluetooth device Promise<void>

Example: Scan and Connect to Device

import { BluetoothManager } from 'react-native-bluetooth-ble';

const scanAndConnect = async () => {
  try {
    await BluetoothManager.start();
    const devices = await BluetoothManager.scanForPeripherals();
    console.log('Found Devices:', devices);

    if (devices.length > 0) {
      const device = devices[0];
      await BluetoothManager.connectToDevice(device.id);
      console.log('Connected to:', device.name);
    }
  } catch (error) {
    console.error('Bluetooth Error:', error);
  }
};

4. Reading Bluetooth Characteristics

Property Description Notes
serviceUUID Unique identifier for the Bluetooth service Must be a valid UUID string
characteristicUUID Unique identifier for the characteristic within a service Must be a valid UUID string
isNotifying Indicates if notifications are enabled for the characteristic Boolean value

Example: Reading a Bluetooth Characteristic

import { BleManager } from 'react-native-ble-manager';

const readCharacteristic = async (deviceID, serviceUUID, characteristicUUID) => {
  try {
    const value = await BleManager.readCharacteristicForDevice(
      deviceID,
      serviceUUID,
      characteristicUUID
    );
    console.log('Characteristic value:', value);
  } catch (error) {
    console.error('Failed to read characteristic:', error);
  }
};
Note: Ensure the device is connected and the characteristic is readable before attempting to read.

5. Writing to Bluetooth Devices

Property Description Notes
device.id Unique identifier for the Bluetooth device Required to establish connection
service.uuid UUID of the Bluetooth service to write to Must match the device's advertised services
characteristic.uuid UUID of the characteristic to write to Must be writable and supported by device
value Data to write to the characteristic Can be a byte array or string depending on device

Example: Writing to a Bluetooth Characteristic

import { BleManager } from 'react-native-ble-manager';

const writeToDevice = async () => {
  const deviceId = 'device-id-here';
  const serviceUuid = 'service-uuid-here';
  const characteristicUuid = 'characteristic-uuid-here';
  const data = new Uint8Array([0x48, 0x65, 0x6C, 0x6C, 0x6F]); // "Hello"

  try {
    await BleManager.write(
      deviceId,
      serviceUuid,
      characteristicUuid,
      data
    );
    console.log('Data written successfully');
  } catch (error) {
    console.error('Failed to write data:', error);
  }
};
Note: Ensure the device is connected and the characteristic supports write operations before attempting to write data.
Warning: Writing invalid data or to a read-only characteristic may cause device errors or disconnection.

6. Implementing BLE Communication

Example: Connecting to a BLE Device

import { BleManager } from 'react-native-ble-manager';

const manager = new BleManager();

const connectToDevice = async (deviceId) => {
  try {
    await manager.connectToDevice(deviceId);
    console.log('Connected to device');
  } catch (error) {
    console.error('Connection failed:', error);
  }
};
Method Description Notes
connectToDevice(deviceId) Connects to a BLE device by ID Must be called after scanning
discoverServices(deviceId) Discovers GATT services Required before reading/writing characteristics
readCharacteristic(deviceId, serviceId, characteristicId) Reads a characteristic value Returns data in base64 format
writeCharacteristic(deviceId, serviceId, characteristicId, value) Writes a value to a characteristic Value must be base64 encoded
Note: BLE operations are asynchronous and must be handled with proper error handling.

Example: Reading a BLE Characteristic

const readData = async (deviceId, serviceId, characteristicId) => {
  try {
    const data = await manager.readCharacteristic(deviceId, serviceId, characteristicId);
    const stringValue = Buffer.from(data, 'base64').toString();
    console.log('Received data:', stringValue);
  } catch (error) {
    console.error('Read failed:', error);
  }
};

Example: Writing to a BLE Characteristic

const writeData = async (deviceId, serviceId, characteristicId, message) => {
  try {
    const buffer = Buffer.from(message);
    const base64Data = buffer.toString('base64');
    await manager.writeCharacteristic(deviceId, serviceId, characteristicId, base64Data);
    console.log('Data written successfully');
  } catch (error) {
    console.error('Write failed:', error);
  }
};

7. Setting Up NFC Permissions

Example: Android Manifest Permissions

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />
</manifest>
Permission Description Platform Support
android.permission.NFC Required to access NFC functionality on Android devices. Android
Note: On iOS, NFC is only available on devices that support NFC tags and requires specific hardware capabilities.

8. Reading NFC Tags

Property Description Values
tag.id Unique identifier of the NFC tag string
tag.type Type of NFC tag (e.g., NDEF, Mifare) string
tag.payload Data payload stored on the NFC tag string

Example: Reading NFC Tag Data

import { NfcManager } from 'react-native-nfc-manager';

const readNfcTag = async () => {
  try {
    await NfcManager.requestTechnology(NfcTech.Ndef);
    const tag = await NfcManager.getTag();
    console.log('Tag ID:', tag.id);
    console.log('Tag Payload:', tag.payload);
  } catch (error) {
    console.error('Failed to read NFC tag', error);
  }
};
Note: Ensure NFC permissions are granted in your app's manifest and runtime.
Warning: NFC reading may not work on all devices due to hardware or OS limitations.

9. Writing to NFC Tags

Property Description Values
tagId Unique identifier for the NFC tag string
data Data to be written to the NFC tag string
format Format of the data to be written (e.g., NDEF, Text) string

Example: Writing to an NFC Tag

import { NfcManager } from 'react-native-nfc-manager';

const writeNfcTag = async () => {
  try {
    await NfcManager.registerTagEvent();
    const tag = await NfcManager.getTag();
    const data = 'Hello, NFC!';
    await NfcManager.writeNdefMessage(tag.id, data);
    console.log('Data written to NFC tag');
  } catch (error) {
    console.error('Failed to write to NFC tag', error);
  }
};
Note: Ensure NFC is enabled on the device and the tag is within range before attempting to write.

10. Handling NFC Errors

Error Code Description Solution
NFC_ERROR_UNKNOWN Unspecified NFC error occurred Check device NFC support and permissions
NFC_ERROR_NOT_SUPPORTED Device does not support NFC Gracefully degrade or notify user
NFC_ERROR_PERMISSION_DENIED App lacks NFC permissions Request necessary permissions from user
NFC_ERROR_TAG_LOST Tag was removed before read/write completed Implement retry logic or notify user
NFC_ERROR_IO_ERROR Input/output error during NFC operation Verify tag is readable/writable and retry

Example: Error Handling in NFC Read

import { NfcManager } from 'react-native-nfc-manager';

const readNfcTag = async () => {
  try {
    const tag = await NfcManager.readNdef();
    console.log('Tag data:', tag);
  } catch (error) {
    if (error.code === 'NFC_ERROR_TAG_LOST') {
      console.warn('NFC tag was removed too quickly');
    } else if (error.code === 'NFC_ERROR_PERMISSION_DENIED') {
      console.error('NFC permission denied');
    } else {
      console.error('Unknown NFC error:', error);
    }
  }
};
Note: Always handle NFC errors gracefully to provide a good user experience.

Was this article helpful?