Bug(s) or Feature(s)

Bluetooth Classic Module

Access Adapter/External Accessory features


To access the Adapter/External Accessory related features you're going to be working with the RNBluetoothClassic object.

import RNBluetoothClassic, {
  BluetoothDevice
} from 'react-native-bluetooth-classic';

Common API

The following are available on both Android and IOS.

isBluetoothAvailable

isBluetoothAvailable(): Promise<boolean>

Requests whether the device supports Bluetooth. If Bluetooth is supported, returns true. Otherwise, returns false.

try {
  await available = RNBluetoothClassic.isBluetoothAvailable();
  this.setState({ available });
} catch (err) {
  // Handle accordingly
}

isBluetoothEnabled

isBluetoothEnabled(): Promise<boolean>

Requests whether the device Bluetooth adapter is enabled true or disabled false.

try {
    await enabled = RNBluetoothClassic.isBluetoothEnabled();
    this.setState({enabled});
} catch (err) {
    // Handle accordingly
}

getBondedDevices

getBondedDevices(): Promise<BluetoothDevice[]>

Requests an array of the bonded/paired BluetoothDevice(s).

try {
    await paired = RNBluetoothClassic.getBondedDevices();
    this.setState({paired});
} catch (err) {
    // Error if Bluetooth is not enabled
    // Or there are any issues requesting paired devices
}

getConnectedDevices

getConnectedDevices(): Promise<BluetoothDevice[]>

Requests an array of the connected BluetoothDevice(s); in this context conncted means an active Socket.

try {
    await connected = RNBluetoothClassic.getConnectedDevices();
    this.setState({connected});
} catch (err) {
    // Error if Bluetooth is not enabled
    // Or there are any issues requesting paired devices
}

getConnectedDevice

getConnectedDevice(address: string): Promise<BluetoothDevice>

Requests whether a device BluetoothDevice is currently connected; in this context conncted means an active Socket.

try {
    let address = this.props.device.address;
    await device = RNBluetoothClassic.getConnectedDevice(address);
    this.setState({device});
} catch (err) {
    // Error if Bluetooth is not enabled
    // Or there are any issues requesting paired devices
}

onBluetoothEnabled

onBluetoothEnabled( listener: BluetoothEventListener<StateChangeEvent> ): BluetoothEventSubscription

Adds a BluetoothEventListener<StateChangeEvent> which is notified when the device enables Bluetooth.

componentDidMount() {
    this.enabledSubscription = RNBluetoothClassic.onBluetoothEnabled(this.onStateChange);
}

componetWillUnmount() {    
    this.enabledSubscription.remove(); // don't forget!
}

onStateChange(event: StateChangeEvent) {
    this.setState({ enabled: event.enabled });
}

onBluetoothDisabled

onBluetoothDisabled( listener: BluetoothEventListener<StateChangeEvent> ): BluetoothEventSubscription

Adds a BluetoothEventListener<StateChangeEvent> which is notified when the device disables Bluetooth.

componentDidMount() {
    this.disableSubscription = RNBluetoothClassic.onBluetoothDisabled(this.onStateChange);
}

componetWillUnmount() {    
    this.disableSubscription.remove(); // don't forget!
}

onStateChange(event: StateChangeEvent) {
    // little reverse action
    this.setState({ enabled: !event.enabled });
}

onStateChanged

onStateChanged( listener: BluetoothEventListener<StateChangeEvent>) : BluetoothEventSubscription

Adds a BluetoothEventListener<StateChangeEvent> which is notified when the device enables or disables Bluetooth.

componentDidMount() {
    this.subscription = RNBluetoothClassic.onStateChanged(this.onStateChange);
}

componetWillUnmount() {    
    this.subscription.remove(); // don't forget!
}

onStateChange(event: StateChangeEvent) {
    this.setState({ enabled: event.enabled });
}

onDeviceConnected

onDeviceConnected( listener: BluetoothEventListener<BluetoothDeviceEvent> ): BluetoothEventSubscription

When a device opens a new Socket connection. This was a hold over from the original library and I'm not entirely sure whether it will be used with the advent of BluetoothDevice#connect(), but it's here.

componentDidMount() {
    this.subscription = RNBluetoothClassic.onDeviceConnected(this.onDeviceConnected);
}

componetWillUnmount() {    
    this.subscription.remove(); // don't forget!
}

onDeviceConnected(event: BluetoothDeviceEvent) {
    this.setState({ device: event.device });
}

onDeviceDisconnected

onDeviceDisconnected( listener: BluetoothEventListener<BluetoothDeviceEvent> ): BluetoothEventSubscription

Provides a listener for events fired when Socket connections are: closed, dropped, failed, etc. This was a hold over from the original library, it's a little more useful as a global check on connetivity than just using the BluetoothDevice#disconnect() function.

componentDidMount() {
    this.subscription = RNBluetoothClassic.onDeviceDisconnected(this.onDeviceDisconnected);
}

componetWillUnmount() {    
    this.subscription.remove(); // don't forget!
}

onDeviceDisconnected(event: BluetoothDeviceEvent) {
    let device = this.state.device; // Or loop through paired devices
    device.connected = false;
    this.setState({ device });
}

onError

onError( listener: BluetoothEventListener<BluetoothDeviceEvent> ): BluetoothEventSubscription

Handles any and all errors that occur on the native side. These can be from a connected BluetoothDevice or just from the module. For that reason, you need to check event.device before attempting to use it.

componentDidMount() {
    this.subscription = RNBluetoothClassic.onError(this.onError);
}

componetWillUnmount() {    
    this.subscription.remove(); // don't forget!
}

onDeviceDisconnected(event: BluetoothDeviceEvent) {
    if (event.device) {
        // Handle device error
    } else {
        // Adapter related error
    }
}

Android API

The following are available only on Android.

openBluetoothSettings

openBluetoothSettings(): void

Opens Android's Bluetooth Settings activity.

RNBluetoothClassic.openBluetoothSettings();

startDiscovery

startDiscovery(): Promise<BluetoothDevice[]>

Requests that the BluetoothAdapter be placed into discovery mode. This will resolve with an array of discovered BluetoothDevice(s). You'll need to ensure that you've requested fine location permissions within Android prior to starting:

async requestAccessFineLocationPermission() {
  const granted = await PermissionsAndroid.request(
    PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
    {
      title: 'Access fine location required for discovery',
      message:
        'In order to perform discovery, you must enable/allow ' +
        'fine location access.',
      buttonNeutral: 'Ask Me Later"',
      buttonNegative: 'Cancel',
      buttonPositive: 'OK'
    }
  );
  return granted === PermissionsAndroid.RESULTS.GRANTED;
};

startDiscovery = async () => {
  try {
    let granted = await requestAccessFineLocationPermission();

    if (!granted) {
    throw new Error(`Access fine location was not granted`);
    }

    this.setState({ discovering: true });

    try {
    let unpaired = await RNBluetoothClassic.startDiscovery();
            
    Toast.show({
        text: `Found ${unpaired.length} unpaired devices.`,
        duration: 2000
    });
    } finally {
    this.setState({ devices, discovering: false });
    }      
  } catch (err) {
    Toast.show({
    text: err.message,
    duration: 2000
    });
  }
}
Errors:

Will throw an error if:

  • The BluetoothAdapter is disabled
  • The BluetoothAdapter is already in discovery
Requests:
  • Start discovery for a specific device
  • Provide a DEVICE_DISCOVERED event for intermediate handling

cancelDiscovery

cancelDiscovery(): Promise<boolean>

Cancels the discovery process. This will automatically resolve the startDiscovery promise with the already found BluetoothDevice(s).

cancelDiscovery = async () => {
  try {
    let cancelled = await RNBluetoothClassic.cancelDiscovery();
  } catch(error) {
    Toast.show({
      text: `Error occurred while attempting to cancel discover devices`,
      duration: 2000
    });
  }
}  
Error:

Will throw an error if:

  • The BluetoothAdapter is disabled
  • The BluetoothAdapter is not already in discovery

pairDevice

pairDevice(address: string): Promise<BluetoothDevice>

Attempts to pair the specified device.

Note I haven't actually used or spent any time testing this. It was a hold over from the original library. Feel free to update me with information on whether this is working.

Parameters

address: string the address of the device to be paired. This will be provided by the BluetoothDevice.address found from discovery.

unpairDevice

unpairDevice(address: string): Promise<boolean>

Attempts to unpair the specified device.

Note I haven't actually used or spent any time testing this. It was a hold over from the original library. Feel free to update me with information on whether this is working.

accept

accept(properties: Map<string,object>): Promise<BluetoothDevice>

Places the device into accept mode. This is done (DelimitedConnectionAcceptImpl) by opening a BluetoothServerSocket and resolving with the first BluetoothDevice which connects.

acceptConnections = async () => {
    this.setState({ accepting: true });
      
    try {      
      let device = await RNBluetoothClassic.accept({});
      this.setState({device});
    } catch (error) {
      // Handle error accordingly
    } finally {
      this.setState({ accepting: false });
    }
  }
Parameters

properties: Map<string,object> is determined by the type of connection that you are attempting. This depends highly on the native configuration of your ACCEPT connection type.

cancelAccept

cancelAccept(): Promise<boolean>

Attempts to cancel the accept state. This will resolve the accept promise with a null value. I'm torn on whether this should throw instead, but both of them don't sit well with me.

cancelAcceptConnections = async () => {
    if (!this.state.accepting) {
      return;
    }

    try {
      await RNBluetoothClassic.cancelAccept();
      this.setState({ isAccepting: false });
    } catch(error) {
      // Handle error accordingly
    }
  }

requestBluetoothEnabled

requestBluetoothEnabled(): Promise<boolean>

Request that Android enable the BluetoothAdapter. This will resolve true if Bluetooth is already enabled or the user manually turns the adapter on.

setBluetoothAdapterName

setBluetoothAdapterName(name: string): Promise<boolean>

Attempt to change the name of the BluetoothAdatper.

This is another hold over from the original library. I'm not sure if it's in use, but it's marked as deprecated for now without any plans to remove it.

IOS API

There are no current (and probably no future) IOS only API.