Il existe une application Android interne pour l'inventaire sur le terrain des équipements dans les entrepôts et les chantiers de construction. Désormais, cela fonctionne uniquement en ligne : scanner des codes QR/barres, visualiser des cartes, créer des actes et prendre des photos. Les sites ne disposent souvent pas de réseau, ce qui oblige les employés à prendre des notes dans des notes tierces puis à transférer manuellement les données. Nous devons ajouter un mode hors ligne à part entière avec une synchronisation fiable lorsque Internet apparaît. Environnement technique : Kotlin, Android 10+, MVVM, Retrofit, Room est déjà partiellement utilisé, l'API du serveur ne peut pas être modifiée. Autorisation via OAuth2, le jeton d'accès dure 30 minutes, le jeton d'actualisation est disponible. Le backend fournit des points de terminaison REST : GET /items?updatedSince=timestamp, POST /acts, PATCH /items/{id}, téléchargement de photos en tant que point de terminaison distinct. Le serveur dispose d'un champ version (int) et updateAt (ISO) pour les entités Item et Act, mais il n'y a pas de conflit de résolution sur le serveur. Ce qui doit être mis en œuvre : - Stockage local : étendez le schéma Room pour Item, Act, Attachment, ainsi que les tables d'opérations en attente et les métadonnées de synchronisation. Les données (y compris les champs sensibles et les chemins de pièces jointes) doivent être stockées cryptées sur l'appareil. Il est acceptable d'utiliser Jetpack Security (EncryptedFile/EncryptedSharedPreferences) et/ou SQLCipher pour Android ; justifiez votre choix dans un commentaire au PR. - Changer la file d'attente : toutes les actions de l'utilisateur hors ligne doivent être enregistrées comme des opérations idempotentes (création d'actes, changement de statut, liaison de photos, modification de champs), avec la possibilité de renvoyer sans doublons. Chaque opération nécessite un clientOperationId (UUID) et des règles de resoumission déterministes. - Synchronisation en arrière-plan : via WorkManager (contraintes : réseau connecté, batterie pas faible). Implémentez la synchronisation bidirectionnelle : extrayez les mises à jour du serveur via updateSince, puis envoyez les opérations locales. Prise en charge des interruptions, des erreurs partielles, des délais d'attente du réseau et de l'actualisation des jetons. - Résolution des conflits sur le client : si l'élément a été modifié localement et qu'il a également changé sur le serveur (version/updatedAt), vous devez appliquer une stratégie : la modification locale est prioritaire pour un ensemble spécifique de champs (corriger la liste), mais s'il y a un conflit par statut/responsable - montrer à l'utilisateur un écran de comparaison avec sélection d'une option et enregistrement de la solution. L'écran ne doit apparaître que pour les entités réellement en conflit. - Pièces jointes (photos) : enregistrez les photos localement avec une file d'attente de téléchargement, survivez aux redémarrages de l'application. Limitation : pas plus de 50 Mo au total dans la file d'attente ; en cas de dépassement, affichez une notification claire et bloquez l'ajout de nouvelles pièces jointes jusqu'à la synchronisation/suppression. - Télémétrie : ajoutez un journal de synchronisation local (dans un fichier) avec des niveaux, sans l'envoyer à l'extérieur. Le journal doit contenir le nombre d'opérations, l'heure de synchronisation, le nombre de conflits et les erreurs d'API. Résultat spécifique : PR vers un référentiel avec un mode de fonctionnement hors ligne, migrations de bases de données, tests et brèves instructions sur la façon de vérifier sur l'appareil. Limitations : ne modifiez pas l'API du serveur, ajoutez de nouvelles bibliothèques uniquement lorsque cela est nécessaire et avec un encombrement minimal, prenez en charge Android 10-14, l'application doit fonctionner correctement sans les services Google Play. Critères d'acceptation (mesurables) : 1) En mode avion, vous pouvez : scanner 30 positions, modifier au moins 20 champs pour différents éléments, créer 5 actes et joindre 10 photos - toutes les données sont enregistrées localement et affichées après le redémarrage de l'application. 2) Après avoir activé Internet, la synchronisation est terminée sans doublons : exactement 5 nouveaux actes apparaissent sur le serveur, l'élément n'a pas de modifications en double, les 10 photos sont liées. 3) En cas de conflit créé artificiellement (l'élément est modifié sur le serveur après le dernier pull et le même élément est modifié localement), l'application détecte le conflit et affiche un écran de comparaison ; une fois que l'utilisateur a sélectionné le résultat correspondant à la version sélectionnée, le conflit disparaît à la prochaine synchronisation. 4) La synchronisation en arrière-plan via WorkManager n'est effectuée qu'une fois toutes les 15 minutes, mais le lancement manuel à partir de l'écran des paramètres lance immédiatement la synchronisation. 5) Les données locales sont véritablement cryptées : il est impossible de lire le contenu de la base de données/des fichiers joints en texte clair lorsqu'ils sont copiés depuis l'appareil (il suffit de préciser la méthode de vérification). Étapes attendues : audit de l'architecture actuelle et du schéma de données, conception d'un modèle de synchronisation et de conflits, mise en œuvre du stockage/file d'attente, mise en œuvre du moteur de synchronisation, conflits d'interface utilisateur, tests et stabilisation. Je donnerai accès à : les sources Android, la collection Swagger/request, le banc de test API, plusieurs comptes de test et des scénarios d'utilisateurs sur le terrain.