Fake Friends: concept to product in two days.Read more

How to build

How to Build a Bluetooth App for Android and iOS Hardware

A Bluetooth Low Energy product lives or dies on its phone app, and most of the pain is in connection handling, permissions and firmware updates. This guide covers the decisions a hardware founder has to make, the stack options, and what a first version costs.

Nate Laquis13 min read

What it takes to build a Bluetooth app for Android and iOS hardware

If your product talks over Bluetooth Low Energy, build the first version in React Native with a development build and react-native-ble-plx, unless you need heavy background work, in which case go native with Swift and Kotlin. Budget $60K to $120K and three to five months for a focused app on both platforms, and spend the first two weeks proving the connection with real hardware before you design a single screen.

This guide is for a founder with a BLE product: a sensor, a tracker, a smart lock, a speaker, or a medical-adjacent accessory. You have a prototype board or a first production run, and you need an Android and iOS app that finds the device, connects, moves data back and forth, updates the firmware and survives real life. It is narrower than a general wearable guide. If you are building something worn on the body for health tracking, read the wearable health app guide first. If your device is a ring, the smart ring companion app cost breakdown goes deeper on that category.

The hardest part of a Bluetooth app is not the screens. It is the gap between a demo that works on your desk and a product that works in a pocket, in a car, across forty Android phone models, after an OS update. Almost every decision below is about closing that gap.

Smartphones showing a connected device companion app interface

BLE basics a founder has to decide, not delegate

You do not need to read the Bluetooth specification. You do need to own four decisions, because your firmware engineer and your app team will each assume the other one made them.

GATT: the shape of your data

BLE devices expose data through GATT, a tree of services and characteristics. A characteristic is a value the phone can read, write or subscribe to. Your device might have a battery service, a custom service for sensor readings and another for commands. The design of this tree is a product decision. Keep packets small, version the protocol from day one, and write it down in a document both teams sign off on. A protocol with no version field is the most common reason a firmware update breaks apps that are already in the store.

Decide early between notifications (the device pushes data when it changes) and polling (the phone asks). Notifications are cheaper on battery for both sides. Bulk transfers need sequence numbers and resume support, because they will be interrupted.

Pairing and bonding

Connecting is not pairing, and pairing is not bonding. A connection is temporary. Bonding stores encryption keys so the phone and device can reconnect securely later without repeating the process. Your options run from no security at all, to Just Works pairing (encrypted but with no protection against someone nearby), to passkey or numeric comparison, which needs a display or input on the device. A smart lock should not use Just Works. A cheap environmental sensor probably can. Pick based on what an attacker gains, then write it into the hardware spec before the board is designed, since it affects chip choice and whether you need a button or screen.

Settle the failure cases now: a new phone, a second user, a physical reset. They are support tickets waiting to happen.

Background connection

Decide whether the product has to work with the app closed. A tracker that logs while you walk, a lock that opens as you approach, a glucose-adjacent sensor that syncs overnight: all of these need background behavior, and it is the single biggest driver of platform differences. If the device only matters while the user has the app open, such as a speaker control or a configuration tool, your build gets dramatically simpler and cheaper.

Reconnection

Devices go out of range, phones kill apps, batteries die. Your app needs a reconnection strategy, and it should be designed, not improvised. Remember the last bonded device, reconnect automatically, back off when attempts fail, and show the user plain status ("Connected", "Looking for your device", "Needs attention") instead of a spinner that never ends.

iOS Core Bluetooth versus the Android permission model

The two platforms behave differently enough that treating them as one job with two skins is how schedules slip.

iOS

iOS uses Core Bluetooth. You add a usage description string explaining why the app uses Bluetooth, and the system shows a single permission prompt. iOS does not expose a device's hardware address to apps. It gives you a per-phone identifier instead, so if your backend or support team wants to match a device by its MAC address, you must have the firmware broadcast a serial number or put it in a characteristic.

Pairing on iOS is mostly automatic. When your app touches a characteristic that requires encryption, the system shows its own pairing dialog. You cannot trigger or customize it directly, and you cannot forget a bond from inside your app. The user has to remove the device in Settings. Your onboarding copy needs to say so, because a user who deletes your app and reinstalls it will still have a stale bond on the phone.

Android

Android is where most of the surprises live. Since Android 12, Bluetooth uses runtime permissions called BLUETOOTH_SCAN, BLUETOOTH_CONNECT and BLUETOOTH_ADVERTISE, grouped under the "Nearby devices" permission the user sees. On Android 11 and earlier, scanning requires the location permission, which users find suspicious for a product that has nothing to do with location. If your app does not derive location from scans, you can declare that with the neverForLocation flag on Android 12 and up. You still support older versions with the older permissions, so your manifest and your permission flow have to branch by OS version. Android 13 added a separate Nearby Wi-Fi Devices permission, which matters when you get to provisioning below.

The deeper problem on Android is fragmentation. The Bluetooth stack varies between manufacturers and OS versions. You will meet the generic GATT error 133, connections that fail on the first try and succeed on the second, and bonded devices that refuse to reconnect until Bluetooth is toggled. Teams learn the workarounds only by testing on many phones, which is why the testing section below matters.

Background limits

On iOS, background Bluetooth requires the right background mode in your app's capabilities. Even then, scanning in the background is restricted: you must scan for specific service UUIDs, and discovery is slower and less frequent than in the foreground. For apps that must reconnect after the system has terminated them, Core Bluetooth offers state restoration, where the system relaunches your app in the background when a known device comes into range. Use it if reconnection matters. A user force-quitting the app from the app switcher will stop it, and you cannot work around that.

On Android, background work is governed by battery optimization and foreground service rules. A long-running connection normally means a foreground service with a visible notification, declared with the appropriate service type. Manufacturers add their own aggressive battery managers on top, and some will kill your service no matter what you do right. You will need an in-app guide that tells users how to exempt your app on the worst offenders. Neither platform lets you promise instant background reconnection, so set that expectation in the product design as well as the code.

React Native, native or Flutter for a BLE product

This is the question founders ask first, and the honest answer depends on how much background behavior you need.

React Native is our default pick for most BLE products. The mature option is react-native-ble-plx, and with Expo you use a development build with the library's config plugin, not Expo Go, since Expo Go cannot load custom native Bluetooth code. You share most of the UI, state and business logic across platforms and keep a small amount of platform-specific code for the Bluetooth edges. It suits products where the app is mostly screens, accounts, charts and settings around a device that behaves predictably. For the wider trade-offs, the Expo versus bare React Native comparison helps you decide how much native control you need.

Native Swift and Kotlin is the right call when Bluetooth is the product. That means a lock that must open reliably in the background, a medical-adjacent accessory with strict reconnection requirements, or anything needing state restoration and foreground services tuned carefully. You get direct access to Core Bluetooth and the Android Bluetooth APIs with no library between you and the platform, and you get new OS features on day one. The cost is two codebases, usually 30 to 50 percent more total effort than a shared stack, and two specialists to hire or contract.

Flutter works, and flutter_blue_plus is actively used. We lean away from it for BLE-heavy products because the Bluetooth plugins are thinner, and when something breaks in the background you end up debugging through a plugin and a native layer you did not write.

Keep the Bluetooth layer behind a clean interface so you can swap that one module for native code later without rewriting the app.

Electronic circuit board of a Bluetooth Low Energy hardware prototype

Firmware updates over the air and Wi-Fi provisioning

These two features are where hardware apps become expensive, and where founders most often discover a missing line in the plan.

Firmware OTA (DFU)

You will ship firmware bugs. That is not pessimism, it is the base rate for every connected product. The phone is the easiest delivery path for fixes, so your app needs a device firmware update flow, usually called DFU. If your chip is from Nordic Semiconductor, Nordic provides DFU libraries for iOS and Android, and community wrappers exist for React Native. Other chip families have their own tools, and Zephyr-based firmware commonly uses MCUboot with a management protocol. Ask your firmware engineer which one you are using before you quote the app.

The library handles the transfer. You still build everything around it:

  • Checking the installed version against the latest and deciding whether an update is optional or required.
  • Hosting signed firmware files and verifying them before they go to the device.
  • A battery check, since an update on a nearly dead device is a recipe for a brick.
  • Clear progress and a plain-language failure message with a retry.
  • Recovery when the transfer is interrupted halfway, which requires the bootloader to keep a working image until the new one is verified.

Test it hundreds of times, including pulling the battery mid-update.

Wi-Fi provisioning over BLE

If your device also connects to Wi-Fi, such as a camera, a speaker or a hub, Bluetooth is usually how it receives the network name and password the first time. The phone connects over BLE, sends credentials through an encrypted channel, and the device joins the network. Espressif publishes a provisioning protocol and libraries for its chips that many products use, which saves you from inventing a secure handshake.

Platform details matter. On iOS, the NEHotspotConfiguration API can join a network for the user, and reading the current network name requires specific entitlements and permissions. On Android, the Wi-Fi APIs have changed in nearly every recent release, and Android 13 added the Nearby Wi-Fi Devices permission. Captive portals, 5 GHz-only networks and mistyped passwords all show up in support, so let the user retry without restarting setup.

Offline sync, the data model, testing and store review

Offline sync and the data model

A BLE device is offline most of the time, and so is the phone. Treat the device as one source of truth and the phone as a local store that syncs to your server later. The simple pattern that holds up: the device assigns every reading an ID or sequence number and a timestamp, the phone pulls anything newer than the last acknowledged ID, writes it to a local database (SQLite is the common choice) and then uploads in batches. The phone acknowledges back to the device only after the data is safely stored, so a dropped connection leads to a duplicate, not a loss. Make uploads idempotent on the server so duplicates are harmless.

Cheap devices reset their clock when the battery dies, so have the app write the current time on connect and keep the raw device time too. If you have many users per device or many devices per user, model that relationship in the backend from the start. The offline-first mobile apps guide goes deeper on local storage and sync strategy.

Testing with real devices

Simulators do not do Bluetooth. You need physical phones and physical hardware, and you need them from the first week. Build a small device lab: a few recent iPhones, an older iPhone on an older iOS version, and a spread of Android phones that includes at least one Samsung, one Pixel and one budget model from a manufacturer with aggressive battery management.

Write a test script for the cases that fail in the field: connect with Bluetooth off then turn it on, walk out of range and return, kill the app and wait, reboot the phone, update the OS, swap phones, run an update with a low battery, and connect with other Bluetooth devices active. Every new OS release needs a regression pass, and a person with a phone is still the only reliable BLE test.

Developer testing a mobile app against connected hardware on a desk

Store review

Apple and Google both review hardware apps, and the common problems are predictable.

  • Reviewers do not own your device. Provide a demo mode, a video or a review unit, or you risk a rejection that says they could not use the app.
  • Permission prompts need honest purpose strings. A vague message about Bluetooth gets flagged, and on Android asking for location with no reason does too.
  • Background modes must be justified. Apple asks why your app needs to run in the background, so have a concrete answer.
  • Health or medical wording invites extra scrutiny. If you make medical claims, the regulatory path is a separate workstream. Stay with wellness language until you have a plan with a regulatory advisor.
  • Google Play asks for a data safety declaration and, for some permissions, a declaration of use. Fill them out carefully and keep them aligned with what the app does.

Cost and timeline ranges for a Bluetooth hardware app

These are market ranges for a competent team, not a quote. They move with how complex your device protocol is, how much background behavior you need, and whether you build one platform or two.

  • Connect-and-control app, $40K to $80K, 2 to 4 months. Scan, pair, read and write a handful of characteristics, simple settings, basic onboarding. Often one platform first, or a shared React Native build with a simple device.
  • Focused product on iOS and Android, $60K to $120K, 3 to 5 months. Accounts, background reconnection, local storage with cloud sync, a small set of screens, push notifications and a tested pairing flow.
  • Full product with OTA and provisioning, $120K to $220K, 5 to 8 months. Everything above, plus firmware updates, Wi-Fi provisioning, a backend with device management, analytics and a proper device test lab.
  • Regulated or high-reliability product, $220K and up, 8 months or more. Security reviews, clinical or safety documentation, native implementations for strict background needs and long-term support commitments.

What moves the number most: native versus shared code (30 to 50 percent), background requirements, firmware update reliability, the number of device models you must support, and how much of the protocol is still changing. A protocol that changes weekly while the app is being built is the most expensive situation of all.

Ongoing costs are real too. Plan on 15 to 25 percent of build cost per year for OS updates, library upgrades and device regression testing, plus cloud hosting that starts in the low hundreds of dollars a month and grows with your device count. The smart home IoT app cost guide covers the cloud side in more detail.

How we would build it

If you brought us a BLE product tomorrow, we would not start with design. We would start with the protocol and one ugly screen.

The first version

Week one and two: get your actual hardware talking to an iPhone and an Android phone from a bare test app. Read a characteristic, write one, subscribe to notifications, drop the connection on purpose and reconnect. We would write the GATT protocol document alongside your firmware engineer, with a version field and a clear list of commands. If the hardware is not ready, we would say so and wait, because everything after depends on it.

Then we would build the smallest app that makes the product usable: onboarding with the permission flow handled for each OS version, pairing and bonding, the one or two core screens your users open every day, local storage, and a sync to a simple backend. We would use React Native with a development build and react-native-ble-plx unless your background requirements point to native, and we would decide that in the first two weeks with evidence, not preference. A device lab and a written test script would run from day one. We would put a build in TestFlight and Play internal testing by week six or so, with your real hardware in real hands.

What comes after

Once the connection is proven in the field, the next layer is firmware updates over the air, because you will need them sooner than you expect. After that come Wi-Fi provisioning if the device needs a network, richer sync and device management on the backend, and the analytics that tell you which phones and firmware versions cause trouble. Each of these is easier on top of a protocol and sync layer that were designed on purpose.

The aim is a first release where the device connects the first time, reconnects without drama, and does not need a support email to recover. If you have a BLE prototype and need the Android and iOS apps, bring us the hardware, the protocol notes and your timeline, and we will tell you plainly what it takes. Book a free strategy call

bluetooth app for androidBLE app developmentiOS Core Bluetoothreact-native-ble-plxhardware companion app

Your app, on the App Store.

Thirty minutes. You leave with a plan and a number.

Book a free call