Bluetooth Low Energy

Can react-native-ble-plx connect two phones directly?

No. react-native-ble-plx is a central-role library, and its README lists "communicating between phones using BLE (Peripheral support)" among the things it does not support. A Bluetooth LE link needs one side to advertise and serve data as a peripheral, so two phones running only ble-plx can scan but never find each other. You need a native peripheral module, a different library, or an SDK that runs both roles.

Learning objectives

After reading this article you will be able to:

  • Explain why react-native-ble-plx alone cannot link two phones
  • Identify the iOS and Android APIs that provide the peripheral role
  • Compare the alternatives for phone-to-phone links in React Native by what each needs

What the README says

react-native-ble-plx is a Bluetooth Low Energy library for React Native, maintained by dotintent under the Apache-2.0 license. Its README lists what it supports: observing the Bluetooth adapter state, scanning for BLE devices, connecting to peripherals, discovering services and characteristics, reading, writing, and subscribing to notifications, reading RSSI, negotiating the MTU, and background mode on iOS.

The same README then lists what it does not support. The second item is “communicating between phones using BLE (Peripheral support)”. Bluetooth Classic, bonding, and beacons are on the list too. So the library itself answers whether ble-plx can connect two phones: it cannot.

Bluetooth Low Energy connections are asymmetric. Android’s BLE overview describes the two roles:

  • A central scans for advertisements and starts the connection.
  • A peripheral advertises its presence and accepts the connection. Once connected, it usually acts as the GATT server: it holds the services and characteristics that the central reads, writes, and subscribes to.

A heart-rate strap is a peripheral and a phone is the central. That is the case ble-plx is built for: a phone talking to a sensor, a lock, or a wearable.

Android’s guide states the consequence directly: two devices that only support the central role cannot talk to each other. For two phones to talk, one of them has to play the strap’s part. It must advertise, so the other phone’s scan finds it, and it must host a GATT service, so the other phone has something to read and write. ble-plx only implements the central side. Two phones running it can both scan, but neither is advertising, so neither ever appears in the other’s results.

What it takes to add the peripheral role

Both platforms expose the peripheral role to apps, but through APIs that ble-plx does not wrap:

  • iOS: CBPeripheralManager in Core Bluetooth publishes services and characteristics and starts advertising.
  • Android: BluetoothLeAdvertiser advertises, and BluetoothGattServer hosts the services and answers reads and writes.

Adding these means writing native modules in Swift or Objective-C and Kotlin or Java, then bridging them to JavaScript. After that comes the work the library never had to do: deciding which phone advertises and which scans (or running both on each phone), handling permissions and background limits on each platform, splitting messages to fit the negotiated MTU, and recovering when a connection drops.

The alternatives

Pair ble-plx with a native peripheral module. Keep ble-plx for scanning and connecting, and write or adopt a small module for advertising and the GATT server. A few community packages expose the peripheral role for React Native. Check how recently each was updated, which platforms it covers, and its license before depending on one.

Use a platform peer-to-peer API through a native module. Google’s Nearby Connections offers advertising, discovery, connections, and data transfer between nearby devices, with libraries for Android and for Swift on iOS. Apple’s Multipeer Connectivity does the same between Apple devices only. Both are native libraries, so a React Native app reaches them through a native module. Multipeer Connectivity never reaches an Android phone.

Use an SDK that runs both roles. A mesh or messaging SDK can include the advertising, scanning, GATT service, chunking, and reconnection logic, and often more: encryption between devices, relaying across several phones, and retries. The Offline Protocol mesh SDK is one example for React Native; it is a native module, so it runs in native iOS and Android builds, including Expo development builds, but not in Expo Go.

Which to choose

If you needConsider
A phone talking to a sensor or accessoryble-plx on its own
Two phones exchanging data directly, and you are ready to maintain native codeble-plx plus your own peripheral module
Google’s peer-to-peer API on Android, and on iOS within its documented requirementsNearby Connections through a native module
Apple devices onlyMultipeer Connectivity through a native module
Phones on both platforms, encryption, and relaying across a groupA mesh SDK that runs both BLE roles

Whatever you pick, test on real phones. A simulator build checks that the app is wired up, not that radios deliver, and behaviour differs between iOS and Android, between Android manufacturers, and between foreground and background.

Frequently asked questions

Does the ble-plx Expo plugin's "peripheral" mode add peripheral support?

No. The config plugin's `modes` option adds iOS background mode entries (`peripheral` and `central`) to the app's Info.plist. It declares background permission; it does not add advertising or a GATT server to the library.

Can I use ble-plx for the central side and something else for the peripheral side?

Yes. An app can pair ble-plx for scanning and connecting with a separate native module that advertises and runs a GATT server. Both must agree on the service and characteristic UUIDs, and each phone needs both pieces if either phone may start the connection.

Sources

Build it with Offline Protocol

The Offline Protocol mesh SDK is a React Native native module that connects phones to each other over Bluetooth LE, with discovery, encryption, and relaying included. The quickstart runs it on two physical phones and sends a first message with no account or server.

Read the quickstart