Companion apps for connected devices: Bluetooth, Wi-Fi setup and Matter
How to build a companion app for a connected device: Bluetooth Low Energy basics, Wi-Fi provisioning, pairing UX, permissions, firmware updates and Matter.

Updated 15 Oct 2026
A connected device usually does one thing well: it measures, switches, locks or lights. Everything around that one thing lands in the companion app. Setup, settings, firmware updates, troubleshooting and the moment a user decides whether the product works all happen on a phone screen, often in a hallway, often with the device's manual already in the recycling.
That makes the companion app a strange kind of project. Half of it is ordinary app work, and half is radio protocols, platform permissions and hardware that ships on a different schedule from your code. This guide covers the parts that catch app teams out: Bluetooth Low Energy basics, getting a device onto Wi-Fi, pairing that people can finish, the permissions on iOS and Android, firmware updates, and where Matter fits.
Contains affiliate links. As an Amazon Associate I earn from qualifying purchases.
Bluetooth Low Energy in a few terms
Most connected devices talk to the phone over Bluetooth Low Energy (BLE), at least during setup. The vocabulary is small, and learning it early makes conversations with the firmware team much shorter.
| Term | What it is | In a companion app |
|---|---|---|
| Peripheral | The device that advertises | Your sensor, lock or plug |
| Central | The device that scans and connects | The phone |
| GATT | The profile for exchanging small pieces of data | The device runs a GATT server, the app is the client |
| Service | A group of related characteristics | "Device settings", "Battery" |
| Characteristic | One value, with optional descriptors | A temperature reading, a Wi-Fi status |
| Notify, indicate | The device pushes a changed value | Live readings without polling |
Agree with the firmware team on a tiny protocol written down in one shared document: which services and characteristic UUIDs exist, what each byte means, and a protocol version the app reads first. Apps outlive firmware versions and firmware outlives apps, so both sides need to know which version they are talking to.
Two platform details save debugging time. Android's documentation says scanning is battery-intensive: stop as soon as you find the device, never scan in a loop, and always set a time limit. On iOS, Core Bluetooth gives you an identifier for each peripheral rather than its hardware address, and that identifier means nothing on another phone. If you need a stable device ID across phones and accounts, put it in a characteristic or in the advertising data.
Permissions on iOS and Android
Bluetooth access is a privacy question on both platforms, because a scan for nearby devices can reveal where someone is.
On iOS, an app that uses Core Bluetooth must include NSBluetoothAlwaysUsageDescription in its Info.plist, and Apple's documentation warns that the app will crash without it. If the app also talks to the device over the local network, for example over Bonjour after setup, it needs NSLocalNetworkUsageDescription as well. Since iOS 18, AccessorySetupKit offers a system picker that shows your accessory with your own image and name, and pairing through it grants access to that specific accessory without a broad Bluetooth permission prompt. For new hardware, AccessorySetupKit is worth evaluating before you design a custom flow.
On Android, apps targeting Android 12 or higher declare BLUETOOTH_SCAN to find devices and BLUETOOTH_CONNECT to talk to paired ones, and both are runtime permissions in the Nearby devices group. If the app never derives location from scan results, the neverForLocation flag says so, with one caveat from Google's Bluetooth permissions guide: some BLE beacons are then filtered from results. On Android 11 and lower, scanning needed location permission.
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
Android also has companion device pairing, available since Android 8.0: CompanionDeviceManager scans on your app's behalf with filters you provide, shows a system dialog, and does not require the fine location permission. For a product with one kind of device, it is often the simplest path. Apps targeting Android 13 or higher that manage Wi-Fi connections to nearby devices need NEARBY_WIFI_DEVICES for some Wi-Fi APIs too.
A setup flow people can finish
Ask for permissions when the user starts setting up a device, never at first launch, and explain what is about to happen before the system prompt appears. The guide to onboarding flows people actually finish covers permission priming in more detail. A setup flow that works usually follows this order:
- Check the basics: Bluetooth is on, the device is powered and close by, and the phone is on the Wi-Fi network the device should join.
- Ask for permissions, with one sentence on why.
- Find the device and show only matching devices, never a raw list of everything nearby.
- Confirm it is the right one, for example by making the device blink or asking the user to press its button.
- Send Wi-Fi credentials, if needed, and wait for the device to report the result.
- Show success with the device doing something visible, then let the user name it and pick a room.
Every step needs a failure state that says what to try next. "Couldn't connect" is a dead end; "Move the phone closer and press the button on the device again" is a next step.
Getting the device onto Wi-Fi
Wi-Fi devices need the home network's name and password, and there are two common ways to deliver them.
| Approach | How it works | Watch out for |
|---|---|---|
| Over BLE | The app sends credentials through an encrypted characteristic, the device reports whether it joined | Needs BLE hardware in the device, plus the permissions above |
| Device access point | The device creates its own network, the phone joins it and sends credentials | The phone has no internet while connected, and users get confused |
For the access point route, Android 10 and higher offer WifiNetworkSpecifier for a local connection to the device's network after the user accepts a system dialog, and iOS has NEHotspotConfiguration for joining an accessory's network. In both cases the app should return to the home network on its own and say so.
Whatever the route, report wrong passwords as wrong passwords. Many devices only join 2.4 GHz networks, and many homes broadcast one network name for several bands; tell users which bands the device supports before they type anything.
Firmware updates without bricks
Updates are where companion apps earn trust or lose devices. Ask the firmware team for signed update images that the device verifies before installing, and for two slots, so a failed update falls back to the old version. In the app, check the device's battery before starting, keep the screen awake, show realistic progress, and make the transfer resumable if the connection drops. Updates over BLE are slow; if the device has Wi-Fi, let it download the image itself. Roll out in stages, and keep the app working with at least the previous firmware version, because some devices will sit in a drawer for a year.
Where Matter fits
Matter is a smart home standard maintained by the Connectivity Standards Alliance, with the first version released in October 2022. It runs over Wi-Fi, Thread and Ethernet, uses Bluetooth LE during setup, and devices are added with a QR code or a numeric setup code. Multi-admin means one device can be controlled from several ecosystems at once, such as the home platforms from Apple, Google and Amazon.
For a companion app team, that changes the job. A Matter-certified device can be set up and controlled without your app at all, so your app's role shifts to the features the standard doesn't cover, firmware details, diagnostics and account services. Both Apple and Google provide APIs that let an app hand setup to the system's own Matter flow; check their current documentation before you build a custom one.
Connected devices also go offline more than phones do. The guide to designing for the disconnected user covers the states and sync logic that apply here as well.
Questions
Should the app talk to the device directly or through the cloud?
Directly for setup and for anything that must work when the internet is down, such as a lock. Through the cloud for remote control and history. Most products need both, so design the protocol so the same commands work over either path.
Why did Android ask for location to use Bluetooth?
Because a scan for nearby devices can reveal where someone is. On Android 11 and lower, scanning required location permission; from Android 12, the dedicated Nearby devices permissions replaced it for apps that target that version.
Do we still need our own app if the device supports Matter?
Not for basic control. You may still want one for firmware updates, settings beyond the standard, support and accounts. Make it optional, and never block Matter setup behind it.
How do we test without a pile of prototypes?
A spare phone can play the device, since both platforms let an app act as a BLE peripheral that advertises services on most current phones. Pair that with a few real prototypes, and test on several phone models, as the guide to a small Android test device lab suggests, because Bluetooth stacks differ between manufacturers.
More on mobile development

A powered USB hub for test phones: power, ports and switches
How to choose a powered USB hub for test phones: why bus-powered hubs drop devices, what to read on the spec sheet, and why a switch on every port helps.

Building a small Android test device lab on a budget
How to pick Android test phones by role, buy them refurbished, keep them charged and connected over Wi-Fi, and decide which to update and which to freeze.

Snapshot testing for iOS and Android: a field guide
How snapshot tests work on iOS and Android, which libraries to use, how to record and verify, where flaky diffs come from and what is not worth snapshotting.