Catégories
Plugin et site web

Résolution des problèmes multiplateformes courants lors de l'utilisation de Flutter – Smashing Magazine

A propos de l'auteur

Passionné de Flutter et Linux, auteur du livre Programming Flutter with the Pragmatic Bookshelf. Blogs plus, tweets moins.
Plus à propos
Carmin

Lors de l'utilisation de frameworks multiplateformes, les utilisateurs peuvent oublier les nuances de chacune des plateformes sur lesquelles leur code doit s'exécuter. Cet article vise à répondre à cela.

J'ai vu beaucoup de confusion en ligne concernant le développement Web avec Flutter et, souvent, c'est malheureusement pour de mauvaises raisons.

Plus précisément, les gens le confondent parfois avec les anciennes infrastructures multiplateformes mobiles (et de bureau) basées sur le Web, qui étaient essentiellement des pages Web exécutées dans des navigateurs exécutés dans une application wrapper.

C'était vraiment multi-plateforme dans le sens où les interfaces étaient de toute façon les mêmes car vous n'aviez accès qu'aux interfaces normalement accessibles sur le Web.

Flutter n'est pas cela, cependant: il fonctionne en natif sur chaque plate-forme, et cela signifie que chaque application s'exécute comme si elle était écrite en Java / Kotlin ou Objective-C / Swift sur Android et iOS, à peu près. Vous devez le savoir car cela implique que vous devez prendre soin des nombreuses différences entre ces plateformes très diverses.

Dans cet article, nous allons voir certaines de ces différences et comment les surmonter. Plus précisément, nous allons parler des différences de stockage et d'interface utilisateur, qui sont le plus souvent source de confusion pour les développeurs lors de l'écriture de code Flutter qu'ils souhaitent être multiplateforme.

Exemple 1: stockage

J'ai récemment écrit sur mon blog sur la nécessité d'une approche différente du stockage des JWT dans les applications Web par rapport aux applications mobiles.

Cela est dû à la nature différente des options de stockage des plates-formes et à la nécessité de connaître chacune et leurs outils de développement natifs.

la toile

Lorsque vous écrivez une application Web, les options de stockage dont vous disposez sont les suivantes:

  1. le téléchargement / téléchargement de fichiers sur / depuis le disque, ce qui nécessite une interaction de l'utilisateur et ne convient donc qu'aux fichiers destinés à être lus ou créés par l'utilisateur;
  2. en utilisant des cookies, qui peuvent être accessibles ou non à partir de JS (selon qu'ils sont ou non httpOnly) et sont automatiquement envoyés avec les demandes vers un domaine donné et enregistrés lorsqu'ils font partie d'une réponse;
  3. en utilisant JS localStorage et sessionStorage, accessible par tout JS sur le site, mais uniquement à partir de JS faisant partie des pages de ce site.

Mobile

La situation en matière d'applications mobiles est complètement différente. Les options de stockage sont les suivantes:

  1. documents d'application locale ou stockage en cache, accessibles par cette application;
  2. d'autres chemins de stockage locaux pour les fichiers créés / lisibles par l'utilisateur;
  3. NSUserDefaults et SharedPreferences respectivement sur iOS et Android pour le stockage de valeurs-clés;
  4. Keychain sur iOS et KeyStore sur Android pour un stockage sécurisé, respectivement, des données et des clés cryptographiques.

Si vous ne le savez pas, vous allez gâcher vos implémentations, car vous devez savoir quelle solution de stockage vous utilisez réellement et quels sont les avantages et les inconvénients.

Solutions multiplateformes: une première approche

Utilisation du flottement shared_preferences utilisations du package localStorage sur le Web, SharedPreferences sur Android et NSUserDefaults sur iOS. Celles-ci ont des implications complètement différentes pour votre application, surtout si vous stockez des informations sensibles comme les jetons de session: localStorage peut être lu par le client, c'est donc un problème si vous êtes vulnérable à XSS. Même si les applications mobiles ne sont pas vraiment vulnérables à XSS, SharedPreferences et NSUserDefaults ne sont pas des méthodes de stockage sécurisées car elles peuvent être compromises côté client car elles ne sont pas sécurisées et non chiffrées. C'est parce qu'ils sont destinés aux préférences des utilisateurs, comme mentionné ici dans le cas d'iOS et ici dans la documentation Android lorsque l'on parle de la bibliothèque de sécurité qui est conçue pour fournir des wrappers à la SharedPreferences spécifiquement pour crypter les données avant de les stocker.

Stockage sécurisé sur mobile

Les seules solutions de stockage sécurisé sur mobile sont Keychain et KeyStore sur iOS et Android respectivement, alors que il n'y a pas de stockage sécurisé sur le Web.

le Keychain et KeyStore sont de nature très différente, cependant: Keychain est une solution générique de stockage des informations d'identification, KeyStore est utilisé pour stocker (et peut générer) clés cryptographiques, soit des clés symétriques, soit des clés publiques / privées.

Cela signifie que si, par exemple, vous devez stocker un jeton de session, sur iOS, vous pouvez laisser le système d'exploitation gérer la partie de chiffrement et simplement envoyer votre jeton au Keychain, alors que sur Android, c'est un peu plus une expérience manuelle car vous devez produire (pas de code dur, c'est mauvais) une clé, utilisez-la pour crypter le token, stockez le token crypté dans SharedPreferences et stocker la clé dans le KeyStore.

Il existe différentes approches à cela, comme la plupart des choses en matière de sécurité, mais la plus simple est probablement d'utiliser un cryptage symétrique, car il n'y a pas besoin de cryptographie à clé publique car votre application crypte et décrypte le jeton.

De toute évidence, vous n'avez pas besoin d'écrire du code spécifique à la plate-forme mobile qui fait tout cela, car il existe un plugin Flutter qui fait tout cela, par exemple.

Le manque de stockage sécurisé sur le Web

C'est d'ailleurs la raison qui m'a poussé à écrire ce billet. J'ai écrit sur l'utilisation de ce package pour stocker JWT sur les applications mobiles et les gens voulaient la version Web de cela, mais, comme je l'ai dit, il n'y a pas de stockage sécurisé sur le Web. Ça n'existe pas.

Cela signifie-t-il que votre JWT doit être ouvert?

Non pas du tout. Vous pouvez utiliser httpOnly les cookies, n'est-ce pas? Celles-ci ne sont pas accessibles par JS et sont envoyées uniquement à votre serveur. Le problème, c'est qu'ils sont toujours envoyé à votre serveur, même si l'un de vos utilisateurs clique sur l'URL d'une demande GET sur le site Web de quelqu'un d'autre et que cette demande GET a des effets secondaires que vous ou votre utilisateur n'aimerez pas. Cela fonctionne également pour d'autres types de demande, c'est juste plus compliqué. Cela s’appelle la contrefaçon de demande intersite et vous ne le voulez pas. Il fait partie des menaces de sécurité Web mentionnées dans les documents MDN de Mozilla, où vous pouvez trouver une explication plus complète.

Il existe des méthodes de prévention. Le plus courant est d'avoir deux jetons, en fait: l'un d'eux arrive au client en tant que httpOnly cookie, l'autre dans le cadre de la réponse. Ce dernier doit être stocké dans localStorage et non dans les cookies, car nous ne voulons pas qu'il soit envoyé automatiquement au serveur.

Résoudre les deux

Et si vous avez à la fois une application mobile et une application Web?

Cela peut être traité de deux manières:

  1. Utilisez le même point de terminaison principal, mais obtenez et envoyez manuellement les cookies à l'aide des en-têtes HTTP liés aux cookies;
  2. Créer un point de terminaison backend non Web distinct qui génère différent jeton que l'un ou l'autre jeton utilisé par l'application Web, puis autorisez l'autorisation JWT régulière si le client est en mesure de fournir le jeton uniquement mobile.

Exécution de code différent sur différentes plates-formes

Voyons maintenant comment exécuter différents codes sur différentes plates-formes afin de pouvoir compenser les différences.

Création d'un plugin Flutter

Surtout pour résoudre le problème du stockage, une façon de le faire est d'utiliser un package de plugins: les plugins fournissent une interface Dart commune et peuvent exécuter différents codes sur différentes plates-formes, y compris le code Kotlin / Java spécifique à la plate-forme native ou le code Swift / Objective-C . Le développement de packages et de plugins est assez complexe, mais il est expliqué à de nombreux endroits sur le Web et ailleurs (par exemple dans les livres Flutter), y compris dans la documentation officielle Flutter.

Pour les plates-formes mobiles, par exemple, il existe déjà un plugin de stockage sécurisé, et c'est flutter_secure_storage, pour lequel vous pouvez trouver un exemple d'utilisation ici, mais cela ne fonctionne pas sur le Web, par exemple.

D'un autre côté, pour un stockage de valeurs-clés simple qui fonctionne également sur le Web, il existe un package de plug-in tiers développé par Google et appelé shared_preferences, qui possède un composant spécifique au Web appelé shared_preferences_web qui utilise NSUserDefaults, SharedPreferences ou localStorage selon la plateforme.

TargetPlatform sur Flutter

Après l'importation package:flutter/foundation.dart, vous pouvez comparer Theme.of(context).platform aux valeurs:

  • TargetPlatform.android
  • TargetPlatform.iOS
  • TargetPlatform.linux
  • TargetPlatform.windows
  • TargetPlatform.macOS
  • TargetPlatform.fuchsia

et écrivez vos fonctions pour que, pour chaque plate-forme que vous souhaitez prendre en charge, elles fassent ce qu'il faut. Cela sera particulièrement utile pour le prochain exemple de différence de plate-forme, à savoir les différences d'affichage des widgets sur différentes plates-formes.

Pour ce cas d'utilisation, en particulier, il existe également un flutter_platform_widgets plugin, qui simplifie le développement de widgets compatibles avec la plate-forme.

Exemple 2: différences dans la façon dont le même widget est affiché

Vous ne pouvez pas simplement écrire du code multiplateforme et prétendre qu'un navigateur, un téléphone, un ordinateur et une smartwatch sont la même chose – sauf si vous voulez que votre application Android et iOS soit une WebView et que votre application de bureau soit construite avec Electron . Il y a de nombreuses raisons de ne pas le faire, et ce n'est pas le but de cette pièce de vous convaincre d'utiliser des frameworks comme Flutter à la place qui gardent votre application native, avec tous les avantages de performance et d'expérience utilisateur qui l'accompagnent, tout en vous permettant de écrire du code qui sera la même pour toutes les plateformes la plupart du temps.

Cela nécessite cependant beaucoup de soin et d'attention, et au moins une connaissance de base des plates-formes que vous souhaitez prendre en charge, de leurs API natives réelles, et tout cela. Les utilisateurs natifs de React doivent y prêter encore plus d'attention, car ce cadre utilise les widgets du système d'exploitation intégrés.Vous devez donc réellement prêter encore plus d'attention à l'apparence de l'application en la testant de manière approfondie sur les deux plates-formes, sans pouvoir basculer entre Widget iOS et Material à la volée comme c'est possible avec Flutter.

Quels changements sans votre demande

Certains aspects de l'interface utilisateur de votre application sont automatiquement modifiés lorsque vous changez de plate-forme. Cette section mentionne également les changements entre Flutter et React Native à cet égard.

Entre Android et iOS (Flutter)

Flutter est capable de rendre les widgets Material sur iOS (et les widgets Cupertino (iOS-like) sur Android), mais ce qu'il NE FAIT PAS, c'est de montrer exactement la même chose sur Android et iOS: le thème Material s'adapte en particulier aux conventions de chaque plate-forme .

Par exemple, les animations et les transitions de navigation et les polices par défaut sont différentes, mais celles-ci n'ont pas beaucoup d'impact sur votre application.

Ce qui peut affecter certains de vos choix en matière d'esthétique ou d'UX est le fait que certains éléments statiques changent également. Plus précisément, certaines icônes changent entre les deux plates-formes, les titres des barres d'application sont au milieu sur iOS et à gauche sur Android (à gauche de l'espace disponible au cas où il y aurait un bouton de retour ou le bouton pour ouvrir un tiroir (expliqué ici). dans les directives Material Design et également connu sous le nom de menu hamburger.) Voici à quoi ressemble une application Material avec un tiroir sur Android:

image d'une application Android montrant où le titre de la barre d'application apparaît sur les applications Flutter Android Material
Application matérielle exécutée sur Android: le titre AppBar se trouve dans la partie gauche de l'espace disponible. (Grand aperçu)

Et à quoi ressemble la même application Material, très simple, sur iOS:

image d'une application iOS montrant où le titre de la barre d'application apparaît sur les applications Flutter iOS Material
Application matérielle exécutée sur iOS: le titre AppBar est au milieu. (Grand aperçu)
Entre mobile et Web et avec des encoches d'écran (Flutter)

Sur le Web, la situation est un peu différente, comme mentionné également dans cet article Smashing sur le développement Web réactif avec Flutter: en particulier, en plus d'avoir à optimiser pour des écrans plus grands et à tenir compte de la façon dont les gens s'attendent à naviguer sur votre site – qui est l'objectif principal de cet article – vous devez vous inquiéter du fait que parfois les widgets sont placés en dehors de la fenêtre du navigateur. En outre, certains téléphones ont des encoches dans la partie supérieure de leur écran ou d'autres obstacles au bon affichage de votre application en raison d'une sorte d'obstruction.

Ces deux problèmes peuvent être évités en enveloppant vos widgets dans un SafeArea widget, qui est un type particulier de widget de remplissage qui garantit que vos widgets tombent dans un endroit où ils peuvent réellement être affichés sans que rien n'empêche les utilisateurs de les voir, que ce soit une contrainte matérielle ou logicielle.

Dans React Native

React Native nécessite beaucoup plus d'attention et une connaissance beaucoup plus approfondie de chaque plate-forme, en plus de vous obliger à exécuter le simulateur iOS ainsi que l'émulateur Android au minimum afin de pouvoir tester votre application sur les deux plates-formes: ce n'est pas la même chose et il convertit ses éléments d'interface utilisateur JavaScript en widgets spécifiques à la plate-forme. En d'autres termes, vos applications React Native ressembleront toujours à iOS – avec des éléments d'interface utilisateur Cupertino comme on les appelle parfois – et vos applications Android ressembleront toujours aux applications Android Material Design habituelles car elles utilisent les widgets de la plateforme.

La différence ici est que Flutter rend ses widgets avec son propre moteur de rendu de bas niveau, ce qui signifie que vous pouvez tester les deux versions d'application sur une seule plate-forme.

Contourner ce problème

À moins que vous ne recherchiez quelque chose de très spécifique, votre application est censée être différente sur différentes plates-formes, sinon certains de vos utilisateurs seront mécontents.

Tout comme vous ne devriez pas simplement envoyer une application mobile sur le Web (comme je l'ai écrit dans le post Smashing susmentionné), vous ne devriez pas expédier une application pleine de widgets Cupertino aux utilisateurs d'Android, par exemple, car cela va être déroutant pour la plus grande partie. D'un autre côté, avoir la possibilité d'exécuter une application dotée de widgets destinés à une autre plate-forme vous permet de tester l'application et de la montrer aux gens dans les deux versions sans avoir à utiliser nécessairement deux appareils pour cela.

L'autre côté: utiliser les mauvais widgets pour les bonnes raisons

Mais cela signifie également que vous pouvez effectuer la plupart de votre développement Flutter sur un poste de travail Linux ou Windows sans sacrifier l'expérience de vos utilisateurs iOS, puis simplement créer l'application pour l'autre plate-forme et ne pas avoir à vous soucier de la tester en profondeur.

Prochaines étapes

Les frameworks multiplateformes sont impressionnants, mais ils transfèrent la responsabilité à vous, le développeur, de comprendre comment chaque plate-forme fonctionne et comment vous assurer que votre application s'adapte et est agréable à utiliser pour vos utilisateurs. D'autres petites choses à considérer peuvent être, par exemple, l'utilisation de descriptions différentes pour ce qui pourrait être essentiellement la même chose s'il existe différentes conventions sur différentes plates-formes.

C'est génial de ne pas avoir à créer les deux (ou plus) applications séparément en utilisant des langues différentes, mais vous devez toujours garder à l'esprit que vous créez essentiellement plus d'une application et cela nécessite de réfléchir à chacune des applications que vous construisez .

Autres ressources

Smashing Editorial(ra, yk, il)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *