BLE App Development with React NativeiOS and Android, one codebase
Most app developers do not get far with Bluetooth Low Energy. We build apps that really talk to your hardware: provisioning, live data, offline-first.
- Stable BLE connections
- Provisioning without internet
- Live sensor data in real time
Apps that really talk to hardware
Almost any team can build an app that queries a REST backend. Very few can build an app that holds a stable Bluetooth Low Energy connection to a physical device, reads GATT services, survives connection drops and keeps working in the background. That is exactly where our strength begins.
For years we have built apps that talk directly to sensors, gateways and embedded devices, instead of just showing data from the cloud. That is real engineering at the boundary between hardware and software, not just a pretty interface.
What makes BLE hard in practice
And how we solve it.
Unstable connections
BLE runs in the crowded 2.4 GHz band. Range, interference and supervision timeouts cause drops. We wrap the connection in a state machine with defined states and controlled retries instead of naive promise chains.
Reconnect handling
After a drop a plain connect() is not enough. Services and characteristics must be rediscovered, subscriptions re-established and the app state resynchronised cleanly. We treat reconnect as the normal case, not the exception.
Background scanning
Different rules apply in the background: iOS only scans with an explicit service-UUID filter, throttles intervals and requires the right background modes. We configure it so the app reliably reacts to devices even in the background.
iOS vs Android
CoreBluetooth and the Android BLE stack behave differently: MTU negotiation, permission models (BLUETOOTH_SCAN/CONNECT from Android 12), GATT table caching and bonding. We know the pitfalls of both platforms.
GATT services & characteristics
Data lives in characteristics inside GATT services, often as raw bytes. We read the device protocol correctly, parse little-endian values, flags and scaling and map them onto clean data models.
Pairing & bonding
Pairing flows range from Just Works to passkey entry with an encrypted bond. We build the flow so users in the field get through without a support call, and the bond survives an app restart.
Provisioning without internet
The classic field scenario: a technician faces a brand-new device, no Wi-Fi, no mobile signal, no cloud onboarding. The app handles the entire initial configuration over BLE.
Scan QR
The technician scans the QR code on the device. The app instantly knows the type, serial number and the expected BLE identifier.
BLE connect
The app connects directly to the device over BLE, with no detour through a cloud or local network.
Set parameters
The configuration is written into the characteristics: measurement intervals, thresholds, network keys, calibration. All local, all offline.
Register in backend
Once connectivity is back, the app registers the device in the backend. The registration is queued offline and synced automatically.
Many BLE-configurable devices, such as the LoRaWAN sensors from Milesight, can be commissioned exactly this way.
Live data over BLE
No pull-to-refresh, no 30-second polls. Over BLE notifications the app subscribes to characteristics and gets new values pushed the moment the device sends them. Vibration, temperature, pressure or fill level appear on screen in near real time, with charts that update live.
Real-time notifications
The app subscribes to characteristics and gets new values pushed instead of polling.
Live charts
Incoming bytes land in a ring buffer and render as a smooth, continuously updating chart.
Threshold alerts
If a value crosses a limit, the app alerts immediately, even locally without a backend.
The stack
Proven building blocks, not experiments.
React Native
One codebase for iOS and Android, with access to native modules where it matters.
react-native-ble-plx
The mature BLE library: scanning, connecting, GATT, notifications, across both platforms.
WatermelonDB
Offline-first database for thousands of records, with a sync layer to the backend once connectivity returns.
Here is a minimal scan, connect and read flow with react-native-ble-plx:
import { BleManager } from "react-native-ble-plx";
import { Buffer } from "buffer";
const manager = new BleManager();
const SERVICE_UUID = "0000181a-0000-1000-8000-00805f9b34fb";
const CHAR_UUID = "00002a6e-0000-1000-8000-00805f9b34fb";
manager.startDeviceScan(null, null, (error, device) => {
if (error) {
console.warn(error);
return;
}
if (device?.name === "MerkaioSensor") {
manager.stopDeviceScan();
device
.connect()
.then((d) => d.discoverAllServicesAndCharacteristics())
.then(async (d) => {
const char = await d.readCharacteristicForService(
SERVICE_UUID,
CHAR_UUID,
);
// characteristic.value is base64-encoded
const bytes = Buffer.from(char.value ?? "", "base64");
const tempC = bytes.readInt16LE(0) / 100;
console.log("Temperature:", tempC, "C");
})
.catch((e) => console.warn(e));
}
});iOS and Android from one codebase
You do not need two native teams. React Native provides a shared codebase, while BLE operations run through native modules at full performance. Where one platform needs special behaviour, we address it precisely, without splitting the whole app.
One codebase
One app, two stores, identical behaviour. One budget instead of two native teams.
Native BLE performance
BLE operations run through native modules with full CoreBluetooth and Android BLE performance.
Both stores
Delivery to the App Store and Play Store, including certificates, profiles and review.
Typical projects
Smart product app
The companion app for your hardware product: pair, control, firmware status, settings, all over BLE. In the store under your brand.
Installer app
For technicians in the field: commission, configure and document devices over BLE, even with no internet on site.
Maintenance app
Read live sensor data on site, check limits, capture inspections and log them offline, then sync later.
The Apple hurdle for hardware apps
Apple regularly rejects hardware apps because the reviewer does not have the physical device and cannot test the function. We know the path through App Review: a convincing demo video, precise review notes, a demo mode or test credentials and a clean justification of the Bluetooth and background modes used. That gets IoT apps through approval instead of stuck in endless rounds of questions. Practical knowledge instead of trial and error.
When native is the better choice
Honestly: not every app belongs in React Native. If you need very high-frequency BLE streams with minimal latency, hook deep into OS specifics like CoreBluetooth state restoration or special background scenarios, or already have a native team, then native Swift or Kotlin is often the cleaner solution. We tell you that in the discovery, before you spend money, not after. In the vast majority of IoT app projects, though, the benefits of a shared codebase clearly outweigh the alternatives.
Let us build your hardware app
Bring your idea, we bring the BLE experience. In a discovery we clarify hardware, protocol and scope, and you get a solid concept.
Frequently asked questions about BLE apps
Let's discuss your infrastructure. Digital and on-site.
Whether it's IoT platform development, hardware selection, managed hosting for ChirpStack, ThingsBoard, Grafana or NetBird VPN, or migration from a self-hosted setup - we'll find the right solution for your use case. Book a free 30-minute consultation, no commitment required.
Your contact
Timo Wevelsiep
Founder, merkaio
15 minutes, no commitment, directly with Timo.