BLE device apps: five steps from protocol document to store release
A Bluetooth LE companion app looks small from the outside: pair, read a value, show it. The delivered projects tell a different story — the schedule concentrates in one step, on-device integration, and the most expensive problems are all predictable. The full process is five steps: protocol document review → GATT service mapping → on-device integration → OTA updates → store compliance.
Step 1: read the protocol document before writing code
- Confirm the radio first. BLE and Bluetooth Classic (SPP) have different APIs, different capabilities and different review implications. Pin this down before anything else.
- Ask who defined the GATT layout. If the vendor hands you a protocol document, review it. If all they have is firmware source code, budget time for traffic capture and protocol reconstruction — you will need it.
- Framing and reassembly. When one business message exceeds the MTU, how is it split, and in what byte order is it reassembled? Both sides must agree, in writing.
- Pairing and encryption. The pairing method and key management decide how your app's bonding flow must be written.
- Firmware version range. Which firmware version does the document describe, and which versions are actually in the field? These are rarely the same.
Step 2: map the GATT services into a contract
BLE devices expose their capabilities as GATT services and characteristics, each identified by a UUID. A detail worth keeping for debugging: standard 16-bit UUIDs map onto the Bluetooth SIG base 0000xxxx-0000-1000-8000-00805F9B34FB — the Battery Service is 0x180F and its level characteristic is 0x2A19. Vendor-specific functions usually live under 128-bit custom UUIDs.
Each characteristic carries properties: read, write, write-without-response, notify, indicate. To receive notifications, the client must write an enable flag to the characteristic's CCCD (UUID 0x2902) — when someone reports "we are not receiving data", this is the first place to look.
The deliverable of this step is a service–characteristic–property table: UUID, properties, byte order, framing rules, business meaning. It becomes the shared contract between the app team and the device team, and it outlives both teams' memory.
Step 3: on-device integration, where the schedule goes
Plan for this step to take as long as everything else combined. Nothing in it is conceptually hard; every item below simply surfaces late if nobody planned for it, and late means the hardware is already in the field.
- MTU. The link default is 23 bytes, of which 20 are usable for a GATT write. The app negotiates a larger MTU (via
requestMtuon Android; iOS negotiates automatically) — and the framing logic must survive negotiation failing and falling back to the default. - Background disconnection. iOS restricts BLE events once the app is backgrounded; connections drop or throttle. Design a reconnect state machine from the start, and make state restoration after reconnection idempotent.
- Firmware fragmentation. Two batches of the same device model can behave differently — same service table, different characteristic behaviour. Build a firmware version matrix and regress against the versions you actually ship; testing against the newest firmware alone will fail in the field.
- iOS and Android differences. iOS returns cached scan results; Android needs runtime location or Bluetooth permissions, and its returned MAC address can rotate — never use it as a device identity.
- Log every session. Firmware version, device model, OS version, symptom. These notes become the handover document and the debugging record; without them, every future anomaly investigation starts from zero.
Step 4: OTA updates
- Suspend the business channel during the update and keep only the upgrade service alive.
- Transfer firmware in chunks, each with a sequence number and checksum; retransmit on failure.
- Decide what happens when the user leaves the app mid-update: resume or restart. Decide it explicitly.
- Plan the rollback: if new firmware fails to boot, the boot region must catch it.
- Verify the package matches the device model and current version before flashing — wrong-package bricking is entirely preventable.
Step 5: store compliance
- iOS. The purpose string
NSBluetoothAlwaysUsageDescriptionmust name the actual use — "connects to your BP monitor and syncs readings", not a generic sentence. Vague or missing strings draw rejections. - Android. On Android 12 and above, scanning and connecting use the
BLUETOOTH_SCAN/BLUETOOTH_CONNECTruntime permissions; older versions route scanning through location permission, withneverForLocationwhere location results are not used. - Privacy. The privacy policy must cover what device data is collected and why. The standard release checklist — privacy manifest, review notes, account deletion — applies as usual.
What we have shipped on this path
We have delivered companion apps for health-screening devices, handheld terminals and sensor hardware, and the full chain — protocol reconstruction, GATT integration, OTA, store release — has been run by our own team. The same discipline drives our foot-scanning apps, which drive the phone's depth camera and are live on the US App Store. If you are evaluating a BLE app or taking over a half-finished one, start with the Step 1 checklist against your protocol document: whatever the document is missing now, you will pay back with interest during integration.
Tell us what you want to build.
What the product does, which platforms or devices are involved, and your timing. We reply within three working days, in English, with questions or a short written proposal.