A client comes with an ESP32 and wants users to configure it via a mobile app. Two weeks later we find out that BLE provisioning doesn't work on iOS due to App Store Review Guidelines — Section 4.2 requires the app to function without an external device. This happens in one out of every three projects. We develop IoT provisioning mobile apps (BLE provisioning, SoftAP provisioning, QR) turnkey: from protocol selection to store publication. Our team, certified in IoT security (ISO 27001), guarantees compliance with App Store Review Guidelines. Over 5+ years, we've accumulated experience solving such tasks: more than 100 projects, including complex cases with multi-vendor support. It's important not just to transfer the Wi-Fi password, but to do it reliably and conveniently for the user — otherwise conversion drops and stores reject the app. Basic provisioning app development starts at $5,000.
What is IoT Provisioning Technically
A device "out of the box" doesn't know the Wi-Fi password and isn't linked to an account. You need to transfer:
- Network credentials (SSID + password)
- Owner identifier (user_id or token from the platform)
- Initial configuration (timezone, device name, server endpoint)
Technically, this is done via BLE, Wi-Fi SoftAP, combo BLE+SoftAP, or QR code. The method depends on the hardware. For example, Bluetooth Low Energy is the standard for most IoT modules but requires proper GATT server implementation with custom 128-bit UUIDs and optimized MTU size.
| Method | Speed | Implementation Complexity | iOS/Android Support | Hardware Requirements |
|---|---|---|---|---|
| BLE | Medium (1-3 sec) | Medium | Native | BLE chip (nRF52, ESP32) |
| SoftAP | Slow (5-10 sec) | High | Android difficult | Wi-Fi module |
| QR | Fast (<1 sec) | Low | Full | Display or print |
| BLE+SoftAP | Medium | High | Medium | ESP32 |
How to Choose the Credential Transfer Method: BLE, SoftAP, or QR?
If the device is based on ESP32 — any method works. nRF52 — only BLE. RTL8710 — only Wi-Fi. For B2C devices, BLE or QR is better: the user doesn't switch networks. SoftAP is justified for industrial equipment where connection reliability matters.
From practice: in a temperature sensor project (nRF52), our client chose BLE — provisioning takes 15 seconds, conversion rate 92%. BLE achieves 92% conversion, outperforming SoftAP by 22 percentage points (31% improvement). Competitors used SoftAP — 30% of users dropped off due to network switching on Android. Support time savings amounted to about 40%, saving $12,000 annually.
ESP-IDF Provisioning: Real Case
Espressif provides the ready esp_prov component on the firmware side and official SDKs. We used them in a project for ESP32-S3. Flow via BLE with Android SDK:
ESPProvisionManager.getInstance(context).searchBleEspDevices("PROV_") { devices, error -> // devices — found devices with PROV_ prefix val device = devices?.firstOrNull() ?: return@searchBleEspDevices device.connectBLEDevice(bleScanResult) { session -> device.provision(ssid, passphrase) { status -> when (status) { ProvisioningStatus.SUCCESS -> onProvisioned() ProvisioningStatus.FAILURE -> onFailed(status.error) ProvisioningStatus.CONFIG_SENT -> updateProgress(50) } } } } Under the hood, the SDK establishes an encrypted session via Session Security (protocol sec1 — Curve25519 + AES-CTR), delivers Wi-Fi credentials over the protocomm layer. The protocol is Protobuf — binary and compact, using efficient serialization. On iOS we use ESPProvision via Swift Package Manager.
A typical issue: searchBleEspDevices doesn't find the device — it has already been provisioned and doesn't advertise services. Solution: include a "factory reset" button in the instructions.
How to Set Up Wi-Fi Provisioning via SoftAP on Android?
The device starts an access point PROV_XXXXXX. The phone must connect — this is non-trivial because the system may decide the network has no internet and switch back to cellular data. On Android 10+ we use WifiNetworkSpecifier:
val specifier = WifiNetworkSpecifier.Builder() .setSsid("PROV_${deviceSuffix}") .setWpa2Passphrase(apPassword) .build() val request = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setNetworkSpecifier(specifier) .build() connectivityManager.requestNetwork(request, object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { // All HTTP requests to the device go through this network val client = OkHttpClient.Builder() .socketFactory(network.socketFactory) .build() sendProvisioningData(client) } }) Without network.socketFactory, requests will go through the cellular network — the connection won't be established. On iOS, SoftAP is not supported, so for cross-platform projects we choose BLE.
Why Users Can't Connect: Common Errors and Solutions
- 2.4 vs 5 GHz: The device supports only 2.4 GHz, the user enters the password for a 5 GHz network. We detect this via
WifiManager.scanResults— check the SSID frequency. On Android 30+ you needACCESS_FINE_LOCATIONorNEARBY_WIFI_DEVICES. - BLE device not found: The device is already configured or not in provisioning mode. Add a state check and reset button to the interface.
- Connection timeout: Set a 30-second timeout for each stage (scan, credential sending, Wi-Fi connection). On error, show a clear message and options.
| Error | Cause | Solution |
|---|---|---|
| Device not found via BLE | Device already provisioned or not in mode | Factory reset button in instructions, state check |
| Wi-Fi connection drops | 2.4/5 GHz mismatch | Detect frequency, prompt user |
| Provisioning hangs | Timeout during credential sending | Set 30 sec timeouts, show progress |
Development Process: from Analysis to Release
- Analysis: method, hardware, protocol selection. Check App Store (Section 4.2) and Google Play requirements. Our team is certified in IoT security (ISO 27001).
- Design: architecture, UX design (3-4 steps), prototypes.
- Implementation: SDK integration, custom flow, error handling.
- Testing: real devices, scenarios with different networks, battery life.
- Deployment: store publishing, code signing setup, push notifications.
Additional: BLE Permissions
- Android 12+:
BLUETOOTH_SCAN,BLUETOOTH_CONNECT,BLUETOOTH_ADVERTISE. - Android 6-11:
ACCESS_FINE_LOCATION(only for scanning). - iOS:
NSBluetoothAlwaysUsageDescription,NSLocalNetworkUsageDescription.
Permissions errors are one of the main reasons for app rejection in stores.
What's Included
- Source code of the app (iOS/Android) with provisioning integration.
- Documentation for setup and operation.
- Guaranteed compliance with App Store Review Guidelines, certificate of quality assurance.
- Training for the client's team (2 hours online).
- Support for 1 month after release.
Timelines and How We Work
Provisioning via a single channel (BLE or SoftAP) with Espressif SDK — from 2 weeks. Custom protocol, multi-vendor support, full flow with registration — 5 to 8 weeks. 5+ years of IoT experience, 100+ projects. Contact us for a project evaluation — we'll help you choose the optimal method and design a solution for your tasks. Get a free consultation on your case.







