MONA Android
hiver 2023

Gaspard DM

Voir le rapport final

Semaine 1 (rendez-vous du 25/01)

Rencontre de l'équipe et présentation du projet MONA par Lena via Zoom. Découverte des outils, des enjeux et des problématiques.

Utilisation de l'application Android pour un état des lieux. Téléchargement d'Android Studio et début d'apprentissage de Kotlin.

Semaine 2 (rendez-vous du 01/02)

Apprentissage du Kotlin, familiarisation avec le code de l'application ; je n'ai pas d'expérience en développement Android. Je lis les rapports des anciens étudiants pour avoir une idée globale. Après quelques recherches, je doute qu'il soit plus facile de refaire une app avec React.js (trop de travail), mais j'ai vu Ionic qui pourrait être intéressant.

Update lundi 6 : j'ai patché le bug de l'œuvre du jour (section vide, à cause d'une sélection aléatoire invalide d'une œuvre), qui menait au crash de l'application si l'on essayait depuis la page de l'œuvre du jour de :

  • Prendre une photo ;
  • Cibler l'œuvre d'art ;
  • Accéder à son emplacement sur la carte.

En fait, l'ancien code déterminait l'ID de l'œuvre en partant du numéro de mois notamment, et le divisait par 2. Cependant les mois de janvier et février ont les numéros respectifs 0 et 1, et la division euclidienne par 2 renvoie donc 0 pour ces deux-là, ce qui mène à un ID = 0, qui est bien sûr invalide. J'ai décidé de déterminer l'ID de l'œuvre en initialisant un RNG (Random Number Generator) avec une seed unique dans le temps (JOUR_ANNEE * 10000 + ANNEE), puis en générant un entier entre 1 et la taille de la DB des œuvres.

Je vais essayer de résoudre le problème de caméra qui affecte les Google Pixel d'ici mercredi 8 prochain.

Update mardi 7 : j'ai résolu le problème de l'appareil photo cassé sur les Google Pixel ! Le problème était causé par une mauvaise syntaxe de la fonction dispatchTakePictureIntent de la classe œuvreJourFragment. Normalement le problème ne devrait plus réapparaître.

Update mardi 7, plus tard : il semblerait que le bug persiste hors du contexte de l'œuvre du jour... Le problème, c'est que je n'arrive pas à déterminer la section qui gère ce bouton.

Update mardi 7 (encore) : j'ai enfin réussi à supprimer l'exception levée à l'obtention de certains badges ! Il arrivait qu'un booléen soit null ce qui levait une exception d'assertion.

Semaine 3 (rendez-vous du 8/02)

À la dernière réunion, on a discuté d'une réécriture complète de l'application, en Kotlin ou probablement dans un autre langage avec l'aide d'un framework : quitte à devoir réécrire le code en vue de la migration vers l'API v3, ce serait peut-être une bonne occasion pour faire table rase.

Lena m'a chargé de faire un comparatif des frameworks/langages du marché pour se faire une idée et potentiellement en choisir un. On tombe assez rapidement sur 3 possibilités : Flutter, React Native et Ionic.

Ionic React Native Flutter Kotlin Swift
Performances Bonnes Bonnes Très bonnes Maximales Maximales
Taille APK "Hello world!" 3500 Ko 7000 Ko 7500 Ko 550 Ko ??
Avantage particulier Très facile à apprendre, multi-plateforme Utile pour le multi-plateforme proche des éléments natifs Agréable à développer, performant Natif, 100% compatible JVM, performant Natif, facile à développer, performant
Désavantage particulier Peu adapté aux projets de grande échelle, feeling web Apprendissage relativement difficile Nécessite la connaissance de Dart Verbeux, contraignant, relativement laid Exclusif aux produits Apple

Tous les langages/frameworks peuvent utiliser les composants de l'appareil (caméra, GPS et stockage). J'ai un peu de mal à saisir la différence entre Ionic et React Native, mais je crois qu'alors que React Native manipule des éléments natifs par une sous-couche Kotlin (et passe par le JS pour l'implémentation), Ionic utilise un arbre DOM, en HTML couplé au CSS pour le rendu ; cela vient avec tous les défauts et qualités du Web, notamment pour les performances.

Cependant, le post de blog de Ionic (et malgré son biais évident), montre que les performances des deux se valent, voire une meilleure utilisation GPU d'Ionic selon l'analyseur de Xcode.

Update vendredi 10 : j'ai essayé de reproduire l'interface de base de l'application sur Ionic. Ca semble assez facile, bien que la tentative reste très simple et reste de l'interface.

Semaine 4 (rendez-vous du 15/02)

Nous avons pu rencontrer Guy Lapalme à l'occasion de la dernière réunion. J'ai pu y présenter les différentes alternatives qui se présentent à l'équipe, dans l'optique de reconstruire l'application. De toutes les options, la majorité du groupe a penché vers Ionic.

Je me suis attelé à l'apprentissage d'Ionic auquel est associé Vue.js

J'ai eu du mal à implémenter la carte dans l'application en utilisant Leaflet, si bien que j'ai fini par abandonner au profit d'OpenLayers. L'intégration était beaucoup plus naturelle et c'était plus agréable. Je me suis ensuite concentré sur la création des classes de bases de données de l'application. J'ai pu télécharger les données automatiquement depuis l'API V3, mais je n'ai pas encore réussi à écrire le contenu dans un fichier stable.

Semaine 5 (rendez-vous du 24/02)

Nous avons eu une réunion avec Barbara, la graphiste. Elle a conçu un nouveau tutoriel et nous a expliqué comment se servir de Figma pour exporter les différents assets dont on peut avoir besoin. C'était très intéressant.

Update 25/02 : j'ai réussi à faire en sorte que l'application lise et écrive dans des fichiers.

Update 26/02 : j'ai changé le style de la carte de Watercolor à Toner Lite. C'était marrant mais pas très accessible come style de tuiles.

Update 01/03 : j'a retravaillé la page de découverte du jour. Elle est plus propre en termes de code, et correspond mieux aux mockups du Figma.

Semaine 6 (rendez-vous du 02/03)

Je poursuis le travail de l'application. J'ai essayé de faire un splash screen pour temporiser le temps que l'application récupère les données. Au final, j'ai trouvé une meilleure solution qui consiste à lancer les bases de données avant l'ouverture de l'application pour éviter de lancer l'interface avant le chargement des œuvres. Je compte maintenant travailler sur la prise de photo depuis la page des détails d'une découverte.

Update 04/03 : je suis en train d'implémenter la prise de photos depuis les détails d'une oeuvre. Je travaille aussi sur la page de notation d'une œuvre. L'apparence devrait être terminée pour les 2. Il faut maintenant travailler sur le code interne.

J'ai ajouté la prise de photo, puis j'ai conçu la page de review d'une œuvre. En revanche, impossible de téléverser la photo au serveur. J'ai passé 4 jours à essayer différentes méthodes mais je serveur me renvoie inévitablement une erreur code 422 avec comme "explication" : {'message': 'The given data was invalid.', 'errors': {'photo': ['The photo must be a file of type: jpeg, jpg, png.']}}. J'ai essayé tellement de manière différentes, je me demande si le serveur n'accepte pas un format de données particulier, et la documentation n'est pas assez précise.

Semaine 7 (pas de rendez-vous)

Le problème de téléversement est résolu ! Abdelhakim s'est penché sur le problème et a réussi à trouver un moyen de faire la requête correctement (merci à lui et à Thomas de m'avoir aidé). J'ai donc pu finir le système de prise de photo et ça fonctionne (enfin presque : il arrive que la photo ne soit pas prise en compte localement et ça marche au 2e essai, il faut que je regarde pourquoi).

D'un autre côté, j'ai retravaillé complètement la manière dont les pins sont affichés sur la carte, maintenant tous les pins (peu importe leur asset) sont affichés sur une seule layer alors qu'il en fallait une par asset auparavant (approximativement une dizaine). Je réfléchis aussi à retirer le bouton de changement du fond de carte. En effet, il manque des tuiles aux fonds Stamen à partir d'un certain zoom (issue #97).

J'ai mis en place le système de popup focus sur la carte quand on clique sur une découverte. Normalement tout fonctionne correctement en termes de focus/unfocus automatique (unfocus si on appuie ailleurs par exemple). Idéalement il faudrait que j'augmente la hitbox des pins (ou celle du clic) pour faciliter l'UX.

Semaine 8 (rendez-vous du 16/03)

Nous avons eu le point de mi-session avec M. Lapalme. Il nous a rappelé l'importance du recul sur notre travail, et qu'il fallait qu'on soit prêts à expliquer, avec un esprit critique, le travail effectué au long de la session.

J'ai pu finaliser l'implémentation des pages de connexion et d'inscription. À cause de certains enjeux d'ordre d'exécution et de programmation asynchrones, j'ai aussi décidé d'ajouter une page de chargement des données utilisateur pour préparer l'application avant chaque lancement.

J'ai fait la page de la liste des découvertes. Pour l'instant il n'y a aucun filtre, et elle affiche les découvertes triées par ID (plus simple pour certaines raisons techniques). J'ai aussi fini une implémentation de la géolocalisation. Normalement ça fonctionne OK, mais il faudra s'assurer du bon fonctionnement avec les permissions sur Android Studio.

Semaine 9 (pas de rendez-vous)

J'ai bien avancé sur la structure générale. J'ai pu implémenter :

  • la page Liste (triée alphabétiquement) et une barre de recherche intégrée
  • la page Collection
  • la page Autres
  • les sous-pages "À propos" et "Qui sommes-nous ?"
  • le tutoriel

En plus de cela, j'ai retravaillé l'onglet carte pour améliorer encore les performances : plutôt que de mettre 1 layer par style de feature, j'ai réussi à mettre tous les pins sur une seule layer.

J'ai aussi pu gérer les permissions et le moment où elles sont demandées, et j'ai ajouté une page qui s'ouvre s'il manque des permissions à l'application.

Semaine 10 (rendez-vous du 29/03)

J'ai réussi à implémenter la récupération des données (collection, et photos s'il y en a) au moment de la connexion, ainsi que la fonctionnalité qui permet à la DB de se mettre à jour toute seule. Je n'ai pas pu tester cette dernière cependant, mais le code est assez simple donc je doute qu'il y ait des problèmes. J'ai rencontré un problème : le serveur bloque les requêtes au-delà de 60/minute. J'ai demandé à Natacha d'augmenter cette limite à 240/minute mais il faudra tôt ou tard implémenter une classe pour gérer les temps d'attente forcés.

J'ai mis à jour l'application sur le Play Store en interne avec cette version. C'était assez facile, je m'attendais à avoir des problèmes avec les permissions mais il semble que non. J'en ai profité pour changer les images d'illustration de la page de l'app, qui datent trop et qui sont en trop mauvaise résolution.

Semaine 11 (rendez-vous du 05/04)

J'ai commencé à implémenter la page des badges sur le menu collection. Pour simplifier et accélérer le développement, je ne pars pas (du moins pour le moment) sur l'idée de deux onglets en haut comme sur le Figma, mais sur un bouton centré qui redirige vers un composant Vue. Ca n'est pas optimal mais ça aura le mérite de fonctionner tout autant.

J'ai aussi (enfin) réussi à mettre l'icône à l'application, qui gardait celle par défaut jusqu'à maintenant. J'ai dû télécharger le fichier Illustrator et changer la taille du motif central parce qu'il est trop grand et ne tient pas dans le cercle inscrit (et donc il dépassait, voir exemple). J'ai testé sur Android 13 et ça fonctionne, mais pas encore vérifié sur les versions plus anciennes.

Un test avec un autre appareil m'a fait réaliser que lorsqu'on demande les permissions de géolocalisation alors que le GPS est désactivé, la requête crashe. J'ai résolu ce problème.

Semaine 12 (rendez-vous du 12/04)

Nous avons eu la réunion de test mercredi dernier, qui nous a valu un retour utilisateur très utile. Nous avons trouvé des bugs, ainsi que plusieurs remarques pertinentes concernant l'UX :

Bugs :

  • Le serveur n'accepte pas les images plus grande que 2 Mo par sa configuration (problème critique)
  • La recherche par mots-clefs ne gère pas les lettres accentuées
  • Il arrive que la photo sur la page des détails d'une découverte ne s'affiche pas
  • Il arrive que le titre d'une découverte dépasse du popup sur la carte.

Suggestions d'amélioration de l'UX :

  • Ajouter une estimation de la précision du GPS, qui se met à jour en temps réel
  • Augmenter la taille du bouton "rafraîchir" et changer son icône pour le rendre plus clair
  • Afficher l'adresse ou l'emplacement de la découverte sur sa page des détails
  • Rendre les pages d'inscription/connexion plus claires sur leur nature respective
  • La police de la description d'une découverte est un peu trop petite et difficile à lire.

Les éléments marqués d'un ont été corrigés.

À propos du texte qui dépasse des popups sur la carte, j'en ai retravaillé complètement le CSS. On ne devrait plus avoir ce problème. Le problème du serveur n'est pas encore corrigé mais cela devrait être assez facile, si l'on trouve quelqu'un qui a les droits super user. J'estime que 32 Mo est une limite suffisante pour ne plus rencontrer ce problème du tout. Si c'est trop grand, 16 Mo est, je pense, le minimum absolu. Avec l'augmentation de la qualité photo des appareils ainsi que l'agrandissement du stockage interne, une photo lambda pèse facilement 5+ Mo. De plus, étant donné qu'on donne la possibilité d'envoyer un photo depuis la galerie, il faut s'attendre à ce que les photos puissent atteindre les 10 Mo (un panorama par exemple a une très grande résolution).

Semaine 13 (rendez-vous du 19/04)

Raouf a augmenté la limite de taille des requêtes POST à 8 Mo. Ce n'est pas assez à mon avis mais ça suffira pour conclure la session. Je vais mettre plus de compression sur les photos pour gérer ça.