Développement d’application en Flutter : retours d’expérience (2/2)

Au cours du développement de l’application PeerTube, nous avons acquis certaines expériences dans le choix des technologies employées et les freins que certaines décisions ont entraîné. Nous les partageons ici.

Si vous ne l’avez pas déjà lu, nous vous conseillons de commencer par l’article précédent.

Publication sur les magasins d’application

Publier une application de streaming vidéo issue du fediverse sur les différents magasins d’applications a été un vrai parcours du combattant.

Entre les politiques parfois très strictes des stores, et la sensibilité autour des contenus vidéo — notamment ceux générés ou diffusés par des tiers — il a fallu redoubler de prudence. Apple et Google considèrent en effet qu’en tant qu’éditeur de l’application nous serions responsables de tout le contenu auquel l’application permet d’accéder, et sont particulièrement virulents sur la question dans le cas des formats vidéos (bien davantage que pour une application de podcasts ou même un navigateur internet, assez curieusement). Voici donc un retour sur les différentes étapes, de la toute première soumission à la mise en production.

Les précautions prises

Pour maximiser nos chances d’être acceptés sur les stores, nous avons pris plusieurs précautions dès le départ.

Filtrage des plateformes accessibles

Première mesure : restreindre l’accès aux plateformes via un système de filtrage utilisant des identifiants spécifiques à chaque magasin. Cet identifiant permet de maintenir une liste d’autorisation (allowlist) de plateformes de confiance adaptée à chaque store :

Sur le Play Store (Android), seule une allowlist restreinte de plateformes est accessible afin de répondre aux exigences de Google.

Sur l’App Store (iOS), l’allowlist est encore plus limitée, Apple imposant des critères de validation particulièrement élevés.

Sur F-Droid, en revanche, toutes les plateformes listées dans notre index (qui est modéré) sont accessibles sans filtrage supplémentaire.

L’avantage de ce système basé sur des tags, c’est qu’il est entièrement déporté côté serveur. Autrement dit, si nous devons retirer une plateforme problématique ou en ajouter une nouvelle, cela peut être fait sans mettre à jour l’application elle-même. Ce fonctionnement offre une grande souplesse et réactivité en cas de besoin.

Pas d’ajout manuel de plateformes au début

Pour garantir une validation rapide lors de la première soumission, nous avons volontairement désactivé la possibilité d’ajouter manuellement une plateforme dans l’application. Ainsi, seuls les serveurs autorisés par notre filtre, dont le nombre était très réduit, étaient disponibles.

Une fois l’application validée et disponible sur le Play Store, nous avons réactivé cette fonctionnalité manuelle côté Android, en observant attentivement si cela posait problème. Après plusieurs mois sans retour négatif, nous avons ensuite ouvert cette possibilité sur iOS également.

Présentation et stratégie de déploiement

Par ailleurs, pour mettre toutes les chances de notre côté, un soin particulier a été apporté à l’interface utilisateur de l’application ainsi qu’aux fiches des stores (miniatures, descriptions, mots-clés, captures d’écran, etc.), les stores étant également très sensibles à l’apparence, à la qualité perçue et au respect des bonnes pratiques UX/UI.

Nous avons décidé d’y aller étape par étape :

D’abord le Play Store, plus rapide et souple.

Puis l’App Store, plus exigeant mais incontournable.

Et enfin F-Droid, qui demande une approche différente essentielle pour le public libriste.

Google Play Store, une validation sans accroc

Pour la publication sur le Google Play Store, la documentation officielle Flutter a été suivie : https://docs.flutter.dev/deployment/android

Le Play Store permet plusieurs types de déploiement, utiles pour tester différentes étapes de l’application :

Test interne : permet de distribuer l’application à un petit groupe de testeurs internes (jusqu’à 100).

Test fermé : permet de cibler un groupe restreint plus large via une liste d’adresses email ou un groupe Google.

Test ouvert : permet à n’importe quel utilisateur de rejoindre le programme de test via un lien public.

Production : c’est la version stable, publiée pour tous les utilisateurs sur le Play Store.

Les étapes de validation

Chaque type de déploiement est validé automatiquement par Google, avec des délais très courts :

Les tests internes et fermés sont généralement disponibles en moins d’une heure.

Les tests ouverts et la mise en production peuvent prendre quelques heures, rarement plus.

Google a toujours accepté l’application dès la première soumission, sans demander de modifications ou poser de questions. Aucun échange, aucun retour de leur part : uniquement la validation après envoi et un changelog bien rédigé.
À croire que les précautions mises en place en amont ont été suffisantes… voire qu’on aurait pu être un peu plus détendus !

Apple App Store, les complications…

Une fois l’étape Google franchie haut la main, direction Apple — réputé pour être nettement plus exigeant.

Comme pour Android, j’ai suivi la documentation officielle Flutter pour le déploiement iOS :
👉 Flutter iOS Deployment

Sur iOS, les applications peuvent être distribuées via deux canaux principaux :

TestFlight : pour partager des versions bêta avec un groupe de testeurs (jusqu’à 10 000). Le processus est plus souple que pour la production, mais reste soumis à validation.

Production : la version stable et publique de l’app, visible sur l’App Store.

Les étapes de validation

L’avertissement de Gabe

Avant de soumettre PeerTube sur iOS, nous avons échangé avec Gabe, développeur du projet OwnCast, qui avait essuyé plusieurs refus de la part d’Apple. Il nous a transmis ses précieux retours et stratégies pour répondre aux fameuses App Store Guidelines. Voici un résumé :

Guideline 1.2 – Safety – User Generated Content
➤ Solution : intégrer un système de signalement côté client, qui envoie un email à un modérateur capable de retirer une instance si besoin.

Guideline 5.2.3 – Legal
➤ Problème : Apple considère que l’app pourrait donner accès à des contenus vidéo ou audio tiers sans autorisation, ce qui pose un risque légal.
➤ Solution : fournir un document PDF listant chaque serveur vidéo préconfiguré dans l’app, avec la mention “Authorized” pour chacun. Apple ne se satisfait pas d’une simple déclaration : ils veulent des preuves tangibles.

Guideline 3.1.1 – Business – Payments – In-App Purchase
➤ Problème : l’app permettait de faire des dons via des liens comme PayPal, OpenCollective, KoFi, etc.
➤ Solution : supprimer toute interaction liée au paiement dans l’app. Tous les liens renvoyant vers des dons doivent ouvrir une page dans un navigateur externe (Safari, Chrome…). Aucun lien de paiement ne doit être affiché dans une WebView interne.

Guideline 5.2.3 – Legal (bis)
➤ Solution : fournir un maximum de documents, liens et preuves que les catalogues et services de découverte intégrés sont bien opérés par nous, et non une tierce partie non autorisée.

Merci encore à Gabe pour ces conseils précieux !

On se lance… et ça coince.

Notre plan était pourtant sans accros !

Malgré l’application rigoureuse des conseils de Gabe, Apple n’a pas fait de cadeau.

Entre Lokas et PeerTube, les deux apps que nous tentions de publier fin 2024, nous avons essuyé 8 refus pour Lokas avant d’obtenir la validation, et 3 refus pour PeerTube.

Dès qu’un reviewer Apple trouvait un souci (même mineur), la demande était rejetée, et il fallait corriger point par point avant de pouvoir espérer passer à l’étape suivante.

Voici les principales guidelines qui nous ont posées problème :

Guideline 5.2.3 – Legal

Votre application contient du contenu ou des fonctionnalités susceptibles de porter atteinte aux droits d’un ou plusieurs tiers. Plus précisément, votre application fournit un accès potentiellement non autorisé à des services tiers de streaming audio ou vidéo, à des catalogues et à des services de découverte.

Malgré l’envoi d’un document listant les plateformes autorisées dans l’app iOS, cela n’a pas suffi à convaincre Apple. Nous avons donc répondu :

Les plateformes répertoriées dans l’application PeerTube ont accordé à l’application PeerTube le droit de répertorier et d’accéder à leur contenu vidéo.

Ces autorisations sont répertoriées dans le document « Plateformes autorisées pour l’application PeerTube ».

Pouvez-vous expliquer quel type de preuve nous devons fournir pour démontrer que nous avons le droit d’accéder à ce contenu ?

Le document joint était rigoureusement le même que celui soumis lors du dépôt de l’application.

Guideline 3.1.1 – Business – Payments – In-App Purchase

Apple nous a signalé un lien vers le site joinpeertube.org dans l’app, qui contient… un bouton de don. Ce simple lien externe a suffi à justifier un rejet.

Nous avons alors tenté une première réponse, en expliquant que tous les liens de dons ouvraient désormais une page externe dans le navigateur, et qu’aucune collecte n’était réalisée dans l’application elle-même. Nous avons souligné que cette approche respectait les guidelines de l’App Store, puisque le processus de don était totalement séparé des fonctionnalités de l’app. Malgré cette clarification, Apple n’a pas été convaincu.

En replongeant dans les App Store Guidelines, j’ai repéré un paragraphe en notre faveur :

Section 3.2.2 (iv) : Les applications qui ne sont pas approuvées en tant qu’organisations à but non lucratif ou autrement autorisées en vertu de la section 3.2.1 (vi) peuvent collecter des dons caritatifs en dehors de l’application, par exemple via Safari ou SMS.

J’ai donc renvoyé un message à l’équipe de validation, en expliquant que l’application ne collecte aucun don en interne : tous les liens de soutien ouvrent une page externe dans le navigateur (Safari), conformément à la section 3.2.2 (iv) des App Store Guidelines qui autorise ce fonctionnement pour les apps non caritatives. J’ai ainsi demandé une réévaluation de la décision ou des précisions si d’autres points posaient problème.

🎉 Résultat : l’application PeerTube a officiellement été publiée sur iOS !

Depuis, j’ai soumis 5 mises à jour successives de PeerTube, toutes validées sans accroc — y compris celle qui introduisait la fonctionnalité de connexion.
Chaque mise à jour a été validée en quelques heures, au plus sous 24h.

L’App Store, ce n’est jamais simple… mais avec de la patience et une bonne lecture des guidelines, ça passe.

F-Droid, une autre aventure

Une fois l’étape Apple validée, je me suis attaqué à la soumission sur F-Droid.
Ici, ce n’est pas un problème de guidelines, mais plutôt de processus.

La documentation officielle est plutôt éparse, et j’ai eu du mal à trouver une ressource exhaustive pour un projet Flutter. Je me suis donc appuyé sur :

La documentation “rapide” : https://f-droid.org/docs/Submitting_to_F-Droid_Quick_Start_Guide/

La FAQ développeur : https://f-droid.org/docs/FAQ_-_App_Developers/

Et surtout l’analyse de d’autres applications Flutter déjà présentes sur F-Droid

S’adapter au fonctionnement de F-Droid

F-Droid a des exigences particulières :

Le build doit être reproductible et entièrement libre.

Toute dépendance externe doit pouvoir être vérifiée ou supprimée.

Il faut déclarer les anti-features, c’est-à-dire des limitations qui ne correspondent pas aux idéaux du libre.

Exemple : TetheredNet

L’application PeerTube utilise par défaut deux services maintenus par Framasoft :

instances.joinpeertube.org pour lister les instances disponibles

SepiaSearch pour faire des recherches depuis un compte local

Ces services ne sont pas configurables par l’utilisateur, ce qui a été considéré comme une “anti-feature” du type TetheredNet (connexion à un service centralisé sans possibilité de le changer).

Cette mention a donc été ajoutée lors de la soumission initiale.
Bonne nouvelle : depuis, cette anti-feature a été retirée, car nous avons rendu ces services personnalisables dans l’app.

Dépasser le blocage d’une dépendance obsolète

Avant de parvenir à la validation, nous avons rencontré un obstacle lié à une dépendance utilisée pour la gestion de la base de données locale. Cette bibliothèque, pourtant populaire au moment du choix initial, n’était plus maintenue et ne proposait pas de version compatible avec la dernière version de Flutter requise par F-Droid pour garantir la reproductibilité des builds. Ce blocage a empêché la compilation de l’application sur l’infrastructure F-Droid, rendant impossible sa publication.

Après analyse, il est apparu que la meilleure solution, pour des raisons de pérennité et de sécurité, était de remplacer cette dépendance obsolète par une alternative maintenue et compatible avec les exigences de F-Droid. Ce changement a nécessité une réécriture partielle de la gestion des données locales, mais a permis de débloquer la situation et d’assurer la stabilité du projet sur le long terme.

Le merge request de soumission

Après plusieurs itérations, nous avons enfin pu soumettre notre app sur F-Droid.
Vous pouvez consulter la MR ici : https://gitlab.com/fdroid/fdroiddata/-/merge_requests/17235

Et pour voir la configuration finale de l’application PeerTube sur F-Droid (fichier metadata/*.yml) : https://gitlab.com/fdroid/fdroiddata/-/blob/master/metadata/org.framasoft.peertube.yml

F-Droid demande rigueur et patience, mais l’expérience permet aussi de mieux comprendre les enjeux du libre et de la décentralisation.

C’était un vrai défi, mais on est fier·es de faire partie du catalogue officiel.

Nous en profitons pour vous rappeler que le financement participatif pour le développement de l’application PeerTube est en cours jusqu’au 17 juin 2025 !