Développement d'apps Flutter BLE

Publié le 9 avril 2026

16 min de lecture
Companion app Flutter BLE connectée à du matériel de cyclisme
Jonas Ockerman
Jonas OckermanCo-Founder

Vous avez un produit matériel et il vous faut une app qui va avec. Simple en apparence. Mais dès que le Bluetooth Low Energy entre en jeu, le périmètre s’élargit d’une manière qui ne devient évidente qu’après trois mois de projet.

Nous l’avons appris en construisant la companion app de Classified Cycling, une entreprise belge qui fabrique des transmissions sans fil pour cyclistes. Leur matériel se connecte en BLE, a besoin de mises à jour firmware over-the-air et tourne en extérieur, là où le Bluetooth se comporte de façon imprévisible. L’app gère aujourd’hui les connexions à quatre types de matériel distincts, s’intègre à deux écosystèmes partenaires externes et assure la distribution du firmware pour tous. Ce qui a commencé comme “un écran de pairing et quelques réglages” est devenu une véritable plateforme de connectivité.

Cet article couvre ce qu’exigent réellement les companion apps BLE, pourquoi Flutter s’y prête bien, où se loge la vraie complexité et quelles questions valent la peine d’être posées avant de commencer.

Ce que font vraiment les companion apps BLE

Une companion app est l’interface mobile d’un appareil matériel. Pour la plupart des produits, cela signifie quatre choses :

Pairing et découverte des appareils. L’app scanne les périphériques BLE alentour, identifie le bon appareil (généralement via des données d’advertising propres au fabricant), s’authentifie et enregistre le bond. Sur iOS, le système gère l’état de bonding. Sur Android, vous le gérez vous-même. Les deux diffèrent suffisamment pour constituer, en pratique, deux problèmes d’ingénierie distincts.

Configuration. Une fois appairée, l’app lit et écrit des valeurs de configuration dans les characteristics BLE. Chez Classified Cycling, il s’agit de l’affectation des boutons de commande, des modes de sortie et des seuils de passage de vitesse. Chaque paramètre configurable est une characteristic GATT avec un UUID, un type de données et des droits de lecture et d’écriture.

Télémétrie en direct. Certains appareils diffusent des données en continu. Le hub de Classified envoie le niveau de batterie, l’état de connexion et les changements de vitesse sous forme de notifications BLE. L’app s’abonne à ces characteristics et met l’interface à jour en temps réel. La difficulté est de le faire de façon fiable pendant que le téléphone est dans une poche de maillot, que le hub est sur un cadre de vélo et qu’un peloton de carbone et de métal se trouve entre les deux.

Mises à jour firmware OTA. C’est la partie la plus dure. Pousser du firmware en BLE, c’est transférer plusieurs centaines de kilo-octets sur un canal lent et sujet aux pertes, sans jamais pouvoir briquer l’appareil en cas d’interruption. La plupart des matériels utilisent le protocole Device Firmware Update de Nordic Semiconductor (Nordic DFU) ou un équivalent. L’app orchestre le transfert, gère les retries et doit récupérer proprement si la connexion tombe en cours de route.

Qui façonne le paysage BLE sur lequel les équipes construisent
Nordic Semiconductor
Le DFU et des puces présentes dans d'innombrables périphériques
Apple Core Bluetooth
Bonding iOS, modes d'arrière-plan et règles du store
Stack Bluetooth d'Android
Limites de scan, permissions et politiques d'énergie des OEM

Pourquoi Flutter fonctionne pour le BLE

L’écosystème BLE de Flutter s’est consolidé autour de deux packages bien maintenus : flutter_reactive_ble et flutter_blue_plus. Les deux couvrent tout le cycle de vie d’une connexion. Les deux supportent iOS et Android depuis une seule base de code.

Ce point de la base de code unique compte plus qu’il n’y paraît. Le BLE diverge dès le niveau de l’OS entre iOS et Android. Si vous construisez des apps natives séparées, vous écrivez et maintenez deux stacks BLE distinctes. Avec Flutter, vous écrivez la couche BLE une fois et vous absorbez les différences de plateforme dans une couche circonscrite plutôt qu’à travers deux bases de code.

L’écosystème de plugins est également mature pour des cas d’usage précis. Nordic DFU dispose d’un package Flutter bien suivi. Détection d’iBeacon, profils GATT pour les catégories de matériel courantes, gestion des scans en arrière-plan : ce sont des problèmes résolus par des packages maintenus, pas des choses à construire de zéro.

Pour un décideur : Flutter pour le BLE, c’est une seule équipe, une seule base de code et un écosystème assez profond pour couvrir d’emblée la plupart des besoins d’une companion app. L’alternative réaliste, des équipes natives iOS et Android séparées, coûte plus cher et prend plus de temps pour un résultat fonctionnellement équivalent.

Stacks BLE Flutter face à deux bases de code natives
flutter_reactive_ble
API orientée streams
Une couche Dart
Base de code
iOS + Android
Plateformes
Les pipelines réactifs collent à votre app
Idéal quand
flutter_blue_plus
Alternative largement adoptée
Une couche Dart
Base de code
iOS + Android
Plateformes
Le style callback convient à l'équipe
Idéal quand
Natif iOS + Android
Implémentations séparées
BLE en Swift + Kotlin
Base de code
Logique dupliquée
Plateformes
Contraintes legacy hors Flutter
Idéal quand

Où se loge la vraie complexité

L’écran de pairing est la partie facile. Voici ce qui prend réellement du temps.

iOS et Android ne bondent pas pareil. iOS gère le bonding BLE au niveau de l’OS. Android l’expose au niveau de l’app. Sur iOS, si l’utilisateur réinstalle l’app, l’OS se souvient toujours du bond mais l’identifiant d’appareil stocké par l’app a disparu, si bien que l’app ne retrouve pas ses propres appareils appairés sans rescanner. Sur Android, vous gérez le bonding vous-même. Ces cas limites demandent un traitement explicite.

Les conditions Bluetooth en extérieur. L’app Classified tourne sur des vélos. Le téléphone est dans une poche de maillot, le hub sous la selle, et le cycliste se déplace à 40 km/h dans un champ de carbone et de métal. Le signal BLE ne se propage pas de façon fiable dans ces conditions. L’app a besoin d’une logique de reconnexion automatique, d’un suivi de la qualité de connexion et d’une machine à états qui distingue “déconnecté temporairement” de “l’utilisateur s’est éloigné”.

Le cycle de vie d’une connexion BLE. Une connexion BLE n’est pas un socket. Elle a des états : scan, connexion, découverte des services, authentification, lecture des characteristics, réception des notifications et déconnexion. Chaque état peut échouer, et la récupération diffère à chaque fois. Gérer cela correctement exige une machine à états explicite, pas une série de callbacks. Voici à quoi ressemble le cycle de vie chez Classified :

01Scanner les périphériques correspondant au préfixe fabricant de l’appareil
02Se connecter et découvrir les services et characteristics GATT
03S’authentifier par un handshake challenge-réponse sur une characteristic chiffrée
04S’abonner aux characteristics de notification pour la télémétrie et le statut
05Lire et écrire les characteristics de configuration au fil des interactions
06À la déconnexion, déterminer si elle vient de l’utilisateur ou d’une coupure, et agir en conséquence

Traitement en arrière-plan. iOS et Android limitent tous deux ce qu’une app peut faire en arrière-plan. Si l’app doit maintenir une connexion BLE écran éteint, courant pour les apps de fitness et de cyclisme, il faut gérer explicitement les modes d’exécution en arrière-plan. Les modes d’arrière-plan de Core Bluetooth sur iOS exigent des déclarations de capabilities et restreignent ce que vous pouvez lire. Les restrictions de scan en arrière-plan d’Android se sont durcies avec Android 8, puis à nouveau avec Android 12.

Isolates Dart pour les boucles de scan. Scanner en BLE en continu depuis l’isolate Dart principal dégrade les performances de l’interface. Le bon pattern est de faire tourner la boucle de scan dans un isolate Dart séparé, en renvoyant les résultats à l’isolate d’UI par message passing. C’est le même pattern que nous employons pour les opérations natives bloquantes dans notre travail sur Flutter FFI.

La fenêtre de mise à jour firmware. Une mise à jour OTA prend 2 à 5 minutes sur un lien BLE typique. Pendant ce temps, l’app ne peut pas perdre la connexion, la batterie du téléphone ne peut pas lâcher et l’OS ne peut pas interrompre l’opération. Ce n’est pas un problème d’interface, c’est de l’ingénierie de fiabilité.

Rien de tout cela n’est insurmontable. Mais chaque point demande une ingénierie délibérée, et le temps s’accumule. Si votre équipe n’a jamais livré de companion app BLE, l’estimation de “la couche BLE” est probablement 40 à 60 % en dessous de ce qu’elle devrait être.

App BLE face à une interface web

Tous les appareils connectés n’ont pas besoin d’une companion app native. Web Bluetooth existe et fonctionne dans les navigateurs Chromium. Un dashboard web peut couvrir la configuration et l’affichage du statut pour bien des cas d’usage. Voici comment choisir :

BesoinApp nativeWeb Bluetooth / dashboard web
Mises à jour firmware OTAOuiLimité (transfert de fichier seul)
Connexion BLE en arrière-planOuiNon
Support iOSOuiNon (Apple bloque le Web BLE sur iOS)
Usage hors ligneOuiPartiel
Distribution via app storeObligatoirePas nécessaire
Notifications pushOuiLimité
Profils GATT complexesOuiOui
Première version rapidePlus lentPlus rapide

Web Bluetooth ne tourne que dans Chrome et Edge. Il ne tourne pas du tout sur iOS. Si vos utilisateurs sont sur iPhone, une interface web ne remplace pas complètement une app.

Pour des cas d’usage limités à la configuration, où Android est votre seule plateforme et où les utilisateurs sont assez techniques pour passer par un navigateur, Web Bluetooth se défend. Dès qu’il est question d’iOS, de connectivité en arrière-plan, de mises à jour OTA ou de distribution grand public, il vous faut une app native.

Choisissez une app native quand
Vous avez besoin de mises à jour firmware OTA avec retry et récupération robustes
Le produit doit rester connecté en arrière-plan, écran éteint
Vos utilisateurs sont sur iPhone ou vous avez besoin de l'App Store
Les notifications push ou un parcours d'installation grand public comptent pour l'adoption
Web Bluetooth peut suffire quand
Il s'agit uniquement de configuration sur Android, avec des utilisateurs techniques sur Chrome ou Edge
Les sessions sont courtes et l'onglet peut rester ouvert, sans lien en arrière-plan
Vous optimisez pour la première version la plus rapide et une portée limitée au navigateur suffit

Les questions à poser avant de commencer

Ce sont les questions que nous posons à chaque appel de discovery pour un projet de companion app BLE. Si vous commandez un tel projet, y répondre clairement avant de démarrer fait gagner du temps et évite les surprises de périmètre.

Combien de types d’appareils ? Chaque type d’appareil est une implémentation BLE distincte. Un hub, un capteur et une commande à gérer depuis une seule app, ce sont trois stacks de connexion, pas une.

Quels profils BLE utilisez-vous ? Les profils GATT standards (Heart Rate, Battery, Device Information) ont des packages Flutter existants. Les profils propriétaires demandent un travail d’implémentation du protocole. Le protocole D-Fly de Shimano, par exemple, nous a obligés à implémenter leur séquence de pairing propriétaire de zéro. Nous l’avons détaillé dans l’article sur l’intégration Shimano DI2.

Les mises à jour firmware OTA sont-elles requises ? Cela double la complexité de la couche BLE. Pas au sens figuré. La logique de retry, l’orchestration du transfert et la récupération pour l’OTA représentent à peu près autant d’ingénierie que tout le reste réuni.

L’app doit-elle maintenir une connexion BLE en arrière-plan ? Si oui, ajoutez la gestion des modes d’exécution en arrière-plan sur les deux plateformes, plus les tests sur toute la gamme des variantes de constructeurs Android (Samsung, Xiaomi et Huawei implémentent chacun l’optimisation de batterie à leur façon).

À quoi ressemble l’usage en extérieur ? Les scénarios d’électronique grand public (installation à la maison, configuration occasionnelle) ont des exigences de fiabilité très différentes des scénarios sport et fitness (mouvement constant, signal variable, parfois critique pour la sécurité).

Y a-t-il des exigences réglementaires ? Les dispositifs médicaux, les appareils qui interagissent avec des systèmes critiques et ceux vendus dans des catégories réglementées (automobile, aéronautique, médical) ont des exigences de certification qui touchent l’implémentation BLE.

Quelle est la répartition des plateformes visées ? Si 80 % de vos utilisateurs sont sur iOS, cela change la priorisation. S’il vous faut le support d’Android 8, cela détermine les API disponibles. S’il faut livrer sur les deux plateformes en trois mois, la taille de l’équipe et le périmètre doivent le refléter.

À retenir

L’app Classified a commencé comme un écran de pairing. Quatre ans et plusieurs générations de matériel plus tard, elle gère les connexions à quatre types d’appareils, s’intègre à deux écosystèmes partenaires et tourne dans des conditions pour lesquelles la plupart du code de connectivité n’a jamais été conçu. Cette trajectoire est typique.

Les companion apps BLE ne sont pas des apps qui utilisent accessoirement le Bluetooth. La couche de connectivité est le produit. Concevez-la et construisez-la ainsi dès le départ.

L’avantage de la base de code unique de Flutter est réel sur les projets BLE. La consolidation de l’écosystème de librairies et la possibilité de partager la logique de connexion entre iOS et Android réduisent sensiblement le coût de maintenance dans la durée.

Les mises à jour firmware OTA ne sont pas une fonctionnalité de fin de parcours. Si elles sont requises, cadrez-les dès le début. Les décisions d’architecture qui rendent l’OTA sûr sont difficiles à greffer après coup.

Les questions de la section précédente ne sont pas exhaustives, mais toute équipe incapable d’y répondre clairement avant de démarrer découvrira son périmètre en cours de projet. Les appels de discovery existent pour une raison.

Si vous construisez une équipe qui a migré depuis React Native, l’histoire du BLE sur Flutter est l’un des gains les plus nets. Nous approfondissons la décision de migration dans notre article sur la migration de React Native vers Flutter. Si le BLE est votre moteur principal, Flutter est le bon choix et la migration vaut l’investissement.

L’écosystème de Flutter va au-delà du BLE. Si vous évaluez aussi Flutter pour l’e-commerce, par exemple des parcours scan-to-order avec des scanners de codes-barres Bluetooth, notre article sur l’intégration Flutter et Magento explique comment les deux patterns se rejoignent.

Besoin d'aide pour le développement d'une app BLE ?

Questions fréquemment posées

Études de cas associées