jQueryMobile et PhoneGap : un duo gagnant pour vos applications mobiles ?

Le succès des smartphones, tablettes, et autres mobile devices ne semble, malgré la crise, subir aucun ralentissement : sur 2011 on observe une augmentation des ventes de smartphones de 74% et un total de 63 millions de tablettes vendues. Pour nos clients, cela déclenche une remise en perspective de leur stratégie : “comment proposer mes services mobiles à la population la plus large possible”, “comment m’adapter aux nouveaux canaux de diffusion que sont les App Store et Google Play” ou encore “puis-je maitriser mes coûts de développement et de maintenance sur ces X plateformes”.

Dans cet article, je vais essayer de vous présenter l’approche que j’ai utilisé pour un client. Je ne peux malheureusement pas rentrer dans les détails de ce projet mais sachez cependant que l’approche de développement “hybride” retenue (i.e. application mixte native / web) était un pré-requis du client… Étant plutôt un habitué des développements natifs, j’ai profité de ce projet pour essayer de me forger ma propre opinion. Je vous propose donc dans cet article d’évaluer ce que propose les technologies web pour l’implémentation d’application mobile et bien sûr, leurs limites.

jQueryMobile, les composants graphiques

jQueryMobile est un framework qui permet, à partir de pages HTML5/CSS3, d’obtenir des écrans et des composants graphiques adaptés au rendu sur un écran de smartphone ou tablette.

Il s’agit d’un framework qui se base, évidemment, sur jQuery mais utilise plus particulièrement son cousin jQuery UI pour l’implémentation des composants graphiques (widgets). Il est conçu pour fonctionner sur un grand nombre de navigateurs et de plateformes différentes : chaque plateforme est classée suivant son niveau de support ainsi il est possible de “dégrader” correctement l’application sur un ancien téléphone. Dans la même philosophie que jQuery, il essaye d’être le moins intrusif possible : les pages HTML5 contiennent seulement des attributs HTML5 “data” qui permettent de déclencher le rendu des widgets (la page est alors dite “augmentée”).

Exemple “quick & dirty”

<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title>   <p> [...] </p> <div data-role="page" data-theme="b" id="page1"> <div data-role="header"> <h3> Application XXX </h3> </div> <div data-role="content"> <h2> Page 1 </h2> <ul data-role="listview" data-divider-theme="a" data-inset="true"> <li data-role="list-divider" role="heading">Menu </li> <li data-theme="c"> <a href="#page2" data-transition="slide">Vers Page 2</a> </li> <li data-theme="c"> <a href="#page3" data-transition="slide">Vers Page 3</a> </li> <li data-theme="c"> <a href="#page4" data-transition="slide">Vers Page 4</a> </li> </ul> </div> </div> <div data-role="page" data-theme="b" id="page2"> <div data-role="header"> <a data-role="button" data-direction="reverse" data-rel="back" data-transition="fade" href="#page1" data-icon="arrow-l" data-iconpos="left">Retour</a> <h3> Application XXX </h3> </div> <div data-role="content"> <h2> Page 2 </h2><img src="https://maps.googleapis.com/maps/api/staticmap"> </div> </div>


Comme on peut le voir dans le code ci-dessus, deux DIV portent des attributs “data” qui sont découverts par jQueryMobile. “data-role=page” permet d’indiquer qu’il s’agit d’un écran et “data-theme=b” permet de choisir la charte graphique à utiliser (sachant qu’il dispose de 5 thèmes par défaut). Chaque écran peut-être composé de trois zones : header, content, footer (attribut data-role également) dans lesquels on ajoute ses composants graphiques. Pour ajouter une liste ? Il suffit d’utiliser le tag HTML <ul/> avec un attribut “data-role=listview“.

Cinématique des écrans

Ce framework est conçu pour être utilisé à la fois sur des sites web mobiles (ou finalement jQueryMobile peut-être vu comme une couche de rendu spécifique) mais également sur des applications hybrides (c-a-d installées sur le smartphone). Les pages HTML sont alors être distribuées avec l’application (on parle de pages locales) ou bien téléchargées via AJAX (pages distantes).

Afin de gérer les liens et les formulaires, jQM utilise une approche Hijax : il va ajouter, si cela est possible, un appel Ajax sur l’ensemble des liens pour charger le fragment de page et l’injecter de façon dynamique dans l’arbre DOM. Il déclenche des animations CSS3 afin de proposer une transition adaptée.

Il est également possible de capturer des événements “spécifiques mobile” : swipe, orientationchange, tap, taphold, scroll, etc…

Retour d’expérience

Les points forts sont :

  • Le développement utilise des standards HTML5/CSS3 (et demande donc des compétences plus faciles à trouver sur le marché du travail)
  • Cela s’intègre très bien dans un développement MVC classique : il suffit que le serveur génère directement les pages dans le bon format HTML5 et ca marche tout seul
  • Les composants graphiques par défaut sont plutôt étoffés (tableau, formulaire, liste dépliables, boutons, icône, layout grid)
  • Le système de thèmes et l’outil Theme Roller permettent de créer facilement une charte graphique sans – presque – faire de CSS
  • Un développeur connaissant jQuery UI pourra assez facilement faire ses propres composants graphiques

Les points faibles (qui ne sont pas tous spécifique à jQM, mais plutôt à l’approche HTML5) :

  • L’expérience utilisateur (“User eXperience” comme on dit) est vraiment pauvre par rapport à ce qu’on peut obtenir avec une application native
  • Les performances sont mauvaises, notamment sur les transitions entre écrans sur Android
  • On subit les bugs des différentes versions de WebKit (nous avons eu des problèmes avec Android 2.1 par exemple) et finalement on retrouve les mêmes problématiques qu’avec un développement web classique : debug pas spécialement évident, même s’il existe des outils

PhoneGap et sa galaxie

PhoneGap est un framework qui permet d’encapsuler (on parle aussi de “wrapper”) une application HTML/CSS dans une application native (c-a-d disponible sur les différents Store/Market et visible dans le menu du téléphone). L’application native n’est alors qu’une coquille vide qui permet juste de masquer à l’utilisateur qu’il s’agit de simple pages web.

Suite au rachat de Nitobi (société à l’origine de PhoneGap) par Adobe, le code source de PhoneGap a été reversé à la fondation Apache via le projet Callback Cordova. Après quelques petits accrochages avec le PMC de la fondation sur l’utilisation de Git (PhoneGap étant utilisateur de Git, le projet ne souhaitait pas revenir à SVN :), il semblerait que l’incubation du projet soit sur les rails pour une acceptation comme “Top Level Project“.

Concrètement, il utilise les composants navigateurs (appelé « WebView ») disponibles sur chaque OS mobile et expose – dans ce composant navigateur – un certain nombre de passerelles vers les éléments natifs du téléphone. Évidemment, ces passerelles sont accessibles via le langage Javascript (et plus particulièrement via des flux JSON). Il devient ainsi possible depuis son application HTML/CSS/JS de piloter les éléments physiques du téléphone : caméra, fichiers, liste des contacts.

Contrairement à jQueryMobile, je ne vous ferais pas l’affront de vous présenter un projet d’exemple : la page Get Started du site de PhoneGap est très claire et permet de créer un projet en quelques secondes.

Plug-in : JS/Natif

Tous les plugins PhoneGap sont constitués d’une classe Javascript qui expose la fonctionnalité dans l’application HTML/JS (boîte rouge dans la figure ci-contre). La classe JavaScript (boîte verte dans la figure ci-contre) communique à la couche native grâce à la classe de base en utilisant PhoneGap PhoneGap.exec(). La passerelle native de PhoneGap invoque ensuite le code natif du plugin (boîte de violet dans la figure ci-contre).

La liste des plugins fournit dans le paquet par défaut de PhoneGap est la suivante :

  • Accelerometer : écouter le capteur de mouvement
  • Camera : capturer une photo via l’application dédiée
  • Capture : capturer les flux son/image/vidéo du téléphone
  • Compass : orientation magnétique (N/S/E/O) de l’appareil
  • Connection : informations sur la connectivité DATA
  • Contacts : accès à la base de contacts
  • Device : identifiant du smartphone
  • Events : accès aux événements natifs (batterylow, volumeupbutton)
  • File : lecture / écriture de fichiers
  • Geolocation : réception des coordonnées géographiques
  • Media : lecture de fichier audio
  • Notification : notifications visuelles, sonores et tactiles
  • Storage : accès à une base de données SQL

En plus des plugins gérés directement par le projet PhoneGap, il existe un certain nombre de plugins développés par la communauté sur le site GitHub dédié.

Retour d’expérience

Les points forts de PhoneGap sont :

  • Bonne intégration avec jQueryMobile
  • Permet de rapidement obtenir une application fonctionnelle et déployable sur les Market. Il existe même un système de build automatisé qui permet d’obtenir son application packagée pour les différents OS sans installer un seul SDK (c’est une offre payante proposée par Nitobi)
  • Les plugins fournis en standard permettent de répondre à 80% du besoin pour des applications catalogues/consultation

Les points faibles :

  • Il ne s’agit “que” d’une API Javascript : l’implémentation des méthodes de callback est une charge non-négligeable
  • Il faut bien prendre en compte que si on développe des plugins spécifiques PhoneGap il faudra effectuer ce développement sur chaque plateforme cible (pour la partie native ET la partie Javascript). Seule “l’API” exposée par les méthodes Javascript reste stable entre plateformes, non pas le coeur de PhoneGap.
  • Le niveau de qualité des plugins, notamment de la communauté, est très hétérogène
  • Assez compliqué de faire une application vraiment “offline” : il faut alors utiliser manuellement le localStorage HTML5 + gérer de la synchronisation avec le serveur ensuite + traiter les erreurs JSON/Ajax. Je n’ai pas eu le temps de tester des outils comme OpenMobster pour gérer la synchronisation, mais cela s’annonce prometteur.

Pour quels projets ?

Cette approche “un seul code pour l’ensemble de plateformes” limite le support des fonctionnalités au plus petit dénominateur commun. Il faut donc que le client soit conscient d’obtenir une application juste “moyenne” sur plusieurs plateformes (ie. au total sept OS sont supportés par PhoneGap) plutôt qu’une “très bonne” sur un périmètre plus réduit comme Android et iOS (quand même 70% de part de marché à eux deux). Ce n’est pas un drame mais il ne faut surtout pas s’imaginer que cela répond à 100% des besoins (ou faire imaginer cela au client :).

Je prendrais juste trois exemples pour illustrer quelques limites :

  • L’avantage évident des solutions hybride est de réduire les coûts de développement mais il ne faut pas oublier les coûts de maintenance : le développement hybride ne permet pas de réduire le périmètre de tests. D’autre part, le code étant partagé, une correction de bug devra être testée sur toutes les plateformes pour s’assurer de l’absence de régression
  • La comparaison entre les Android Design Guidelines et les iOS Mobile HIG Guidelines) permet d’identifier que les approches proposées par ces deux plateformes différents parfois radicalement. Proposer une IHM identique pour ses deux plateformes ne pourra logiquement se solder que par un écart entre l’ergonomie de l’application “hydride” et des autres applications de l’OS
  • Il n’est pas possible d’utiliser des services en tache de fond : une fois le composant navigateur fermé, l’application n’existe simplement plus. Il est donc impossible de proposer du push, de synchronisation en tache de fond ou des traitements en parallèles. La norme JavaScript WebWorkers permet théoriquement de lancer plusieurs traitements en parallèle, mais n’est pas supportée par Android

Il faut donc le dire clairement, l’approche proposée par le couple jQueryMobile / PhoneGap même si elle semble sexy n’est pas applicable à n’importe quel projet mobile et il faudra réfléchir au cas par cas pour s’assurer que la technologie employée permet de répondre dans le temps et le budget envisagé par le client.