E-Scooter Sharing App Development
In our practice, we often encounter cases where a scooter sits 50 meters away, the app shows “battery 87%”, the QR code scans—but nothing happens. The scooter’s control unit hangs; the unlock command leaves but no acknowledgment arrives. The user scans again, finally rides. Money is charged twice—average loss of 200 rubles per user. This isn’t hypothetical—it’s a typical first-version IoT scenario without idempotency or transaction state. To avoid such issues, we implement solutions from day one. We’ll assess your project and propose the optimal architecture.
Why BLE Unlocking Is a Must-Have for Scooter Sharing
Scooters are mass micromobility vehicles with cheap IoT modules (Omni, Ninebot, Segway OEM lock). Each manufacturer has its own protocol: Segway Lock Protocol, MQTT-based Omni API, or custom TCP. Unlike a car, a scooter might be out of cellular range during unlock—hence Bluetooth Unlocking as a fallback is critical.
BLE unlocking is key. Most modern IoT locks support BLE close-range: the user approaches, the app discovers the device via CBCentralManager (iOS) or BluetoothLeScanner (Android), sends an encrypted unlock packet directly to the lock without internet. The encryption key is generated server-side at rental start and delivered to the app in advance—classic offline token scheme. By our statistics, implementing BLE fallback reduces failed unlocks by 60%.
The Apple Core Bluetooth Programming Guide recommends implementing state restoration for proper background task handling—we account for this nuance in our design.
BLE unlocking is 3× faster than QR scanning if the user is within 5 meters. Comparison of methods:
| Method | Range | Speed | Security |
|---|---|---|---|
| QR | 0–30 cm | ~1 sec | Depends on encoding |
| NFC | 0–4 cm | ~0.3 sec | Hardware (SE) |
| BLE | 0–10 m | ~0.5–2 sec | Key encryption |
How to Implement QR and NFC Without Bugs
QR scanning is the most common way to identify a scooter. We use AVCaptureSession with AVMetadataObjectTypeQRCode on iOS, CameraX + BarcodeScanner from ML Kit on Android. Important: don’t place the scanning overlay via SwiftUI ZStack over AVCapturePreviewLayer without explicit CALayer z-order—SwiftUI views create an extra CALayer that can cover the camera preview on some iPhone models. We ensure correct behavior on all supported devices.
NFC as an alternative works via Core NFC NFCNDEFReaderSession (iOS) or NfcAdapter.enableForegroundDispatch (Android). On iOS, reading is foreground-only, which limits scenarios but works well for “tap phone to scooter.”
What Are the Pitfalls When Integrating IoT Locks?
IoT lock protocols differ in reliability and speed. For example, Segway Lock Protocol uses a fixed key, while Omni API uses dynamic authentication via MQTT. Protocol choice affects app architecture. Comparison:
| Protocol | Type | Idempotency | Integration Complexity |
|---|---|---|---|
| Segway Lock | Proprietary | Partial | Low |
| Omni (MQTT) | Open | Yes | Medium |
| Custom TCP | Proprietary | Depends on implementation | High |
A typical mistake is lack of idempotency on repeated unlock requests, leading to double charges. Another common problem is improper BLE state restoration, causing the app to lose Bluetooth after an iOS update. In our practice, a scooter-sharing startup with 400 scooters faced mass BLE failure after an iOS update. The cause: missing CBCentralManagerDelegate.centralManager(_:willRestoreState:). The fix took 2 hours. We document such scenarios and include them in our testing checklist.
Geo-Fences and Parking Rules: What Matters
Operators collaborate with cities: no-ride zones, mandatory parking zones, paid zones. These are GeoJSON polygons that the app downloads on startup and updates in the background. Point-in-polygon checks: GMSGeometryContainsLocation (Google Maps) or MKPolygon.contains on iOS. For Flutter—poly_gon package or a custom ray-casting algorithm. When a user tries to end a rental in a prohibited zone, we block the action and indicate the nearest allowed parking. Important: we duplicate zone validation on the server. The client might be an older version or compromised. Our experience shows server-side validation prevents 95% of violations.
Fleet Map and Clustering: How Not to Lose Scooters
With 1000+ scooters in a city, clustering is mandatory. We use Supercluster (ported to iOS/Android/Flutter)—the algorithm runs client-side and quickly rebuilds clusters on zoom change. At zoom > 15, we switch to individual icons with battery indicators: green (>50%), yellow (20–50%), red (<20%). Scooter position updates: WebSocket with server events or periodic refresh every 30 seconds when the map screen is active. We don’t update the entire fleet in the background—that drains battery unnecessarily.
Pricing Mechanics: Where to Count Money?
Scooter sharing often uses composite tariffs: start fee + per-minute rate + peak-hour multiplier. We keep the pricing logic server-side; the app only displays the current cost via WebSocket updated every 10 seconds during a trip. We never compute cost on the client—discrepancies between what the client shows and what the server charges lead to disputes and chargebacks. Average trip cost is 150 rubles, and a failed unlock costs the operator 10 rubles in lost time and potential user churn. Our solutions are PCI DSS Level 1 certified.
What’s Included in the Work
- Audit of scooter IoT modules: protocol, BLE support, manufacturer API.
- Command architecture with idempotency and offline BLE fallback.
- Development of map, QR/NFC, pricing, payment.
- Integration with city geo-fences (GeoJSON from operator or city API).
- Publication on App Store and Google Play, complying with App Store Review Guidelines.
- Technical documentation and team training.
Stages and Timelines
- IoT module audit—1 week.
- Architecture—1–2 weeks.
- MVP development (map → QR → rental → payment → completion)—8–12 weeks.
- BLE, geo-fences, analytics integration—+4–6 weeks.
- Testing and publication—2–4 weeks.
Timelines are refined after analyzing your stack. Get a consultation on your project. Contact us for an estimate—we guarantee transparent pricing and budget lock-in before start.







