Start with the platform pair
The right answer depends on which phones need to talk, so decide that first.
| Phones | Options |
|---|---|
| iPhone and Android | Bluetooth LE, with both roles on each phone |
| Android and Android | Bluetooth LE, or Google’s Nearby Connections |
| iPhone and iPhone | Bluetooth LE, or Apple’s Multipeer Connectivity |
Most consumer and field apps cannot choose their users’ phones, which is why Bluetooth LE is the usual starting point. The platform peer-to-peer APIs are useful when you know the pair. Can an iPhone and an Android phone connect directly without internet? goes through each radio in more detail.
Why it needs native code
Every option here is a native library on iOS and Android, reached from JavaScript through a native module. That rules out Expo Go. The react-native-ble-plx README says plainly that it cannot be used in the Expo Go app because it requires custom native code, and the same applies to every library in this article. Expo’s answer is a development build, which Expo describes as your own version of Expo Go where you can use any native library and change native configuration. Bare React Native projects work the same way: install the module, rebuild the native app, and run it on real phones.
Option one: Bluetooth LE
Bluetooth LE is available to apps on both platforms, but a connection is asymmetric. One phone, the peripheral, advertises and hosts a GATT server; the other, the central, scans, connects, and reads and writes. Android’s BLE overview notes that two devices that only support the central role cannot talk to each other.
That matters because common React Native BLE libraries are built for phones talking to sensors, which only needs the central role. The react-native-ble-plx README lists “communicating between phones using BLE (Peripheral support)” among the things it does not support. To send data phone to phone over BLE you need the peripheral side too:
- write a native module for the peripheral role on each platform, and keep ble-plx or a similar library for the central side;
- adopt a community package that exposes the peripheral role, after checking its platforms, maintenance and license; or
- use an SDK that runs both roles for you.
Can react-native-ble-plx connect two phones directly? covers these routes and the platform APIs behind them.
Option two: platform peer-to-peer APIs
Nearby Connections. Google’s API lets one device advertise, another discover it and request a connection, and both accept before data flows. After that the link is symmetric. Data moves as one of three payload types: bytes, which Google limits to 32k and suggests for metadata or control messages; files of any size; and streams generated on the fly. Google publishes libraries for Android and for Swift.
Multipeer Connectivity. Apple’s framework does discovery and sessions between Apple devices, carrying messages, streams and files. On iOS it uses infrastructure Wi-Fi, peer-to-peer Wi-Fi and Bluetooth personal area networks. It is available only on Apple platforms, so it cannot reach an Android phone.
Community wrappers bring these APIs to React Native. expo-nearby-connections, for example, offers one JavaScript API that uses Nearby Connections on Android and Multipeer Connectivity on iOS. Its README is clear about the limit that follows: cross-platform peer-to-peer between Android and iOS is not supported. A single JavaScript API is not the same thing as a single radio protocol, so check what each wrapper runs underneath before relying on it for mixed pairs. Multipeer Connectivity alternatives that work with Android compares the options.
Moving the data reliably
Whichever link you choose, a few habits make the transfer dependable:
- Chunk large data. BLE characteristics carry short pieces of data, so a photo or a long record has to be split, numbered and reassembled.
- Acknowledge at the application level. A link reporting that bytes were sent is not proof that the other app stored them. Have the receiver confirm once it has saved the item. What is an acknowledgment (ACK)? explains the pattern.
- Make retries safe. Connections drop, so the sender will sometimes resend something that already arrived. Give each item an ID so the receiver can ignore duplicates.
- Test the real conditions. Turn off cellular data and Wi-Fi, try both phones in the foreground and background, and try more than one Android manufacturer.
If you would rather not build the Bluetooth layer, Offline Protocol’s @offline-protocol/mesh-sdk 0.27.0 is one example of a React Native native module that advertises and scans over BLE on each phone, encrypts messages with MLS and reports delivery back to the sender. Its installation guide notes that it does not run in Expo Go; a custom development client or a bare React Native project is required.