Fermer

juin 18, 2020

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


À propos de l'auteur

Passionné de Flutter et Linux, auteur du livre Programming Flutter avec la bibliothèque pragmatique. Blogs plus, tweets moins.
En savoir plus sur
Carmine

Lors de l'utilisation de frameworks multiplateformes, les utilisateurs peuvent oublier les nuances de chacune des plates-formes sur lesquelles leur code doit s'exécuter. Cet article vise à résoudre ce problème.

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 l'ancien Web. les cadres multiplateformes mobiles (et de bureau), qui étaient essentiellement des pages Web exécutées dans des navigateurs exécutés dans une application wrapper.

C'était vraiment multiplateforme dans le sens où les interfaces étaient de toute façon les mêmes parce que vous n'aviez accès qu'à les interfaces normalement accessibles sur le Web.

Flutter n'est cependant pas cela: il s'exécute en mode 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 en charge les nombreuses différences entre ces plates-formes 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

I a 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é pour connaître chacun de leurs outils de développement natifs.

Web

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

  1. téléchargement / téléchargement de fichiers vers / depuis le disque, ce qui nécessite une interaction utilisateur et n'est donc adapté aux fichiers destinés à être lus ou créés par l'utilisateur;
  2. à l'aide de cookies, qui peuvent ou non être accessibles à partir de JS (selon qu'ils sont ou non httpOnly ) et sont automatiquement envoyés avec avec des demandes à un domaine donné et enregistré quand ils viennent dans le cadre d'une réponse;
  3. utilisant JS localStorage et sessionStorage accessible par tout JS sur le site Web, mais uniquement à partir de JS qui fait partie des pages de ce site Web. [19659017] Mobile

    La situation en ce qui concerne les applications mobiles est complètement différente. Les options de stockage sont les suivantes:

    1. documents d'application locale ou stockage en cache, accessible par cette application;
    2. autres chemins de stockage local 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. Porte-clés sur iOS et KeyStore sur Android pour le 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 parce que vous devez savoir quelle solution de stockage vous utilisez réellement et quels sont les avantages et les inconvénients.

    Multiplateforme Solutions: une approche initiale

    Utilisation du package Flutter shared_preferences utilise 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, donc c'est 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 un stockage sécurisé et non chiffrées . En effet, 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 au 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 Porte-clés et KeyStore sur iOS et Android respectivement, alors que il n'y a pas de stockage sécurisé sur le Web .

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

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

    Il y a 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 puisque votre application crypte et décrypte le jeton.

    Évidemment, vous ne pas besoin d'écrire du code spécifique à la plate-forme mobile qui fait tout cela, comme il y a un plugin Flutter qui fait tout cela par exemple.

    Le manque de stockage sécurisé sur le Web [19659013] C'est d'ailleurs la raison qui m'a poussé à écrire ce billet. J'ai écrit à propos de l'utilisation de ce package pour stocker JWT sur des applications mobiles et les gens voulaient la version Web mais, comme je l'ai dit, il n'y a pas de stockage sécurisé sur le Web . Cela 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 est qu'ils sont toujours envoyés à 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 avez gagnés » t comme. 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 est envoyé au client sous la forme d'un cookie httpOnly l'autre dans le cadre de la réponse. Ce dernier doit être stocké dans localStorage et non dans des 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éez un Point de terminaison du backend Web qui génère un jeton différent de celui utilisé par l'application Web et autorise ensuite une autorisation JWT régulière si le client est en mesure de fournir le jeton pour mobile uniquement.

    Exécution d'un 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, d'une façon que vous pouvez faire c'est-à-dire avec un package de plugin: les plugins fournissent une interface Dart commune face et peut exécuter différents codes sur différentes plates-formes, y compris le code spécifique à la plate-forme native Kotlin / Java ou 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 la documentation officielle Flutter .

    Pour les plates-formes mobiles, par exemple, il existe est 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é [19659056] shared_preferences_web qui utilise NSUserDefaults SharedPreferences ou localStorage selon la plate-forme.

    TargetPlatform on Flutter

    Après importation du paquet : 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 afin que , pour chaque plate-forme que vous souhaitez prendre en charge, ils font la chose appropriée. Cela sera particulièrement utile pour l'exemple suivant de différence de plate-forme, à savoir les différences dans la façon dont les widgets sont affichés sur différentes plates-formes.

    Pour ce cas d'utilisation, en particulier, il existe également un flutter_platform_widgets raisonnablement populaire. 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 un navigateur, un téléphone, un ordinateur et une smartwatch sont la même chose – à moins que vous ne souhaitiez 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 le même pour toutes les plates-formes 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 de tous cette. Les utilisateurs natifs de React doivent y prêter encore plus d'attention car ce framework utilise les widgets intégrés du système d'exploitation, vous devez donc réellement prêter plus d'attention à l'apparence de l'application en la testant de manière approfondie sur les deux plates-formes, sans pouvoir basculer entre iOS et widget 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 (de type iOS) sur Android), mais ce qu'il NE FAIT PAS, c'est montrer exactement la même chose sur Android et iOS: le thème des matériaux s'adapte particulièrement aux conventions de chaque plate-forme.

    Par exemple, les animations de navigation et les transitions et les polices par défaut sont différentes, mais celles-ci ne le sont pas

    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 Flutter Applications matérielles Android
    Application matérielle fonctionnant 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 matérielle, 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 Material s'exécutant sur iOS: le titre AppBar est au milieu. ( Grand aperçu )
    Entre mobile et Web et avec des encoches d'écran (Flutter)

    On th 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 pour naviguer sur votre site – qui est l'objectif principal de cet article – vous devez vous inquiéter du fait que parfois des widgets sont placés en dehors de la fenêtre du navigateur. De plus, 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 une 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 à des applications Android Material Design régulières car elles utilisent les widgets de la plate-forme.

    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.

    Contournement de ce problème

    À moins que vous ne recherchiez quelque chose de très spécifique, votre application est censé être différent 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 un application pleine de widgets Cupertino pour les utilisateurs d'Android, par exemple, car cela va être déroutant pour la plupart. D'un autre côté, avoir la possibilité d'exécuter réellement une application qui a des 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.

    Le 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 créer simplement l'application pour le

    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 formidable de ne pas avoir à créer les deux (ou plus) applications séparément en utilisant différentes langues, mais vous devez toujours garder à l'esprit que vous construisez essentiellement plus d'une application et que cela nécessite de réfléchir à chacune des applications que vous créez.

    Autres ressources

     Smashing Editorial ( ra, yk, il)




Source link