Cordova - Part 1

Bonjour ! Cette semaine c’est Cordova. Bon clairement, j’ai une guerre de retard (voir deux) car Cordova est un projet utilisé depuis des années maintenant. Dans mes projets pro, il est régulièrement utilisé et c’est pour cela que j’aimerais en connaître d’avantage sur ce projet. (Part1 : car suite à un impératif, je n’ai pas la journée mais l’après-midi).

Objectifs

L’objectif est assez simple : utiliser Cordova et avoir l’application Hello World sur mon téléphone. En bonus: mettre une application Angular 2 en cours de développement sur le même téléphone

Présentation

Cordova (existant depuis maintenant quelques temps) ne manque pas de documentation. La documentation officielle (ici) est assez claire sur ce que permet de faire Cordova.

D’une manière très macro et sûrement réductrice, il est possible de dire que Cordova est la possibilité de faire une application mobile via les technologies HTML/CSS/JS. Le code réalisé au sein d’une WebApp (une application web quoi) va être ensuite exécuté au sein d’une WebView qui va être spécifique à chaque OS Mobile ciblé. C’est d’ailleurs là qu’il peut y avoir parfois des petites surprises …

En plus de permettre la génération de livrables compatibles avec différents OS, Cordova livre également différents plugins (natifs ou non) qui vont permettre d’intéragir avec des éléments physiques du mobile car la caméra, la géolocalisation, etc…

Docker

Cela devient une habitude, mais évidemment, j’ai commencé par me faire une image Docker. Rien de bien compliqué par rapport à la semaine dernière. Juste quelques infos :

  • Il semble qu’un device ne puisse pas être connecté à deux instances adb. Donc il faut penser à le couper sur l’hôte
  • Il faut exécuter Docker avec l’option –privileged afin de lui donner accès à tous les devices (ici)

Ce qui est étrange, c’est que je n’avais pas eu besoin de cela la dernière fois …

Premiers pas

Génération

Cordova arrive avec un outil en ligne de commande permettant de générer, construire, … La première commande à exécuter est donc de générer un projet :

cordova create [path] [id] [name]

. L’id correspond au nom unique de l’application. C’est l’identifiant technique de l’application. name … c’est name. La documentation indique qu’il est possible de changer les valeurs mais qu’il est préférable de ne pas se tromper au démarrage (par expérience, effectivement, c’est galère).

Pour mes premiers pas, j’utilise la commande suivante

cordova create firstStep bzh.devbieres.cordova.firstStep DevBieresFirstStep 

selection_034

La commande est rapide et génère simplement le squelette du projet. Comme cela ne sert à rien de traduire ce qui est bien expliqué : Directory Structure.

Le répertoire important est le répertoire www/ qui va contenir le code de l’application qui sera ensuite intégré dans le code spécifique des plateformes. D’ailleurs, la documentation insiste plusieurs fois sur le fait de mettre en conf ce répertoire et pas forcément plugins/ ou plateforms/

Le fichier de configuration

Alors, je vous invite vraiment à aller lire la documentation sur le fichier de configuration car non seulement c’est intéressant mais on se rend également compte que pas mal de chose se passe dans ce fichier et qu’il y a bien quelques clés spécifiques.

Ajout de la plateforme

Par défaut, aucune plateforme n’est intégré. Il faut l’ajouter manuellement. Pour ce faire, il faut utiliser la commande :

cordova platform add android --save 

. Déjà, ça bosse plus :

selection_035

En fait, la commande a généré un dossier Android dans platform/ et ce répertoire contient les différents éléments nécessaires pour “construire” un livrable compatible avec la platforme cible. A ce stade de l’apprentissage, il n’est pas nécessaire d’en savoir beaucoup plus car “normalement”, il n’est pas nécessaire d’aller modifier des choses dans les fichiers générés. C’est même déconseillé car à la prochaine génération, les éléments seront écrasés.

Premier build

Simple comme une ligne de commande :

cordova build 

. Dans ce cas, toutes les plateformes sont passées en revu. Bon, comme il n’y en a qu’une … autant dire que cela ne change pas grand chose.

A la fin de la commande, un apk est disponible en mode debug pour un déploiement en test.

Feignant

Un bon développeur est un feignant qui laisse la machine faire un maximum de chose. Donc, on va la laisser déployer pour nous le package :

cordova run 

. Encore une fois, cela fonctionne directement car le projet ne contient qu’une cible. Dans le cas, où plusieurs cibles existent :

cordova run android 

pour android.

Une fois tous les petits soucis de connexion, de droits, de mode debug, etc :

screenshot_2016-11-04-15-56-11

MY GOD, IT’S WORKING !!

Vous noterez que j’ai quand même modifier le titre par défaut. Classe :)

Intégrer une application existante

Angular 2 / Ionic

L’objectif est maintenant d’avoir une application existante intégrée dans Cordova. Sous le coude, j’ai une application Angular2. En toute logique, il faudrait passer par Ionic qui dans sa version 2 (en plus d’autres choses) effectue le lien entre Angular 2 & Cordova. Mais bon, Ionic est dans la liste d’un autre demain.

Préparation

En guise de préparation, j’ai “buildé” mon projet Angular2 via la commande suivante :

ng build --target=production --environment=prod --output-path=prod

. J’ai ensuite créer un nouveau projet Cordova dans lequel j’ai simplement remplacé le répertoire www par le répertoire prod du build Angular.

Un commande cela donne quelque chose :

cordova create monapp [...]
cd monapp
rm -r www/
cp -r [monprojetangular]/prod www

Mode Browser

Avant d’aller sur android, un passage par le mode “browser”. Ce mode permet de travailler dans un navigateur ce qui doit être pratique pour certains tests qui ne nécessitent pas forcément un device. Le souci est que la commande

cordova run browser 

lance un navigateur après avoir monté le serveur web. Étant dans un container Docker, je n’ai pas les navigateurs d’installés.

Pour palier à cela, je suis allé dans le répertoire plateforme afin de modifier le lancement :

if(args.target != "none") {
  return cordovaServe.launchBrowser({target: args.target, url: projectUrl});
} else {
   return; 
}

Voilà ! Ca marche.

Cela m’a permis de voir que dans le cas d’un exécution de mon code Angular2 dans le serveur Cordova, un reload de la page renvoyait une erreur 404. Chose que je n’ai pas dans le cas d’une exécution au travers du serveur fourni par angular-cli …

Mode Android : le build

Lancement de la commande :

cordova build android 

. Bim, une première erreur : Error: Duplicate resources . Dans le build Angular, des fichiers js généré sont zippés mais les deux versions restent présentes. Cette double présence semble poser au build Cordova. A creuser mais pour le moment, je supprime les fichiers Gz et le build fonctionne.

Mode Android : le lancement

Lancement de la commande :

cordova run android 

. L’apk se génère bien et l’application se lance. Par contre, elle reste en loading. J’imagine qu’il y a une erreur mais pas de message.

Limite de mon environnement de dev

Je suis arrivé à un point où j’ai une limite dans mon environnement de développement ou de mes connaissances. En effet, comme le smartphone ne peut pas être à la fois associé au container et à la machine hôte, je ne peux pas builder et debugguer via chrome://inspect (qui semble un peu la seule solution quand on recherche rapidement). Il faut tuer adb d’un côté etc… pas pratique.

Trouve pas le fichier

A priori l’erreur semble venir du fait qu’il ne trouve pas les fichiers js depuis le fichier index.html. En creusant, je suis tombé sur cette page qui finalement essaye de faire le même chose que moi (c’est beau Internet). Il faut donc reprendre depuis le build Angular

Intéressant : ils ont également le souci de gz mais ne semble pas trop avoir cherché le pourquoi. Par contre, ils ont scripté leur processus … pas moi (encore)

Recommencer

Bon, on recommence :

cd [monprojetangular]
ng build --target=production --environment=prod --output-path=prod --base-href .
cd [monprojetcordova]
rm -r www/
cp -r [monprojetangular]/prod www
rm www/*.gz
cordova run android

Y’a du mieux …

L’application se lance mais c’est pas encore ça. Les traductions ne fonctionnent pas. En regardant la documentation du plugin, il est noté que dans le cas de Ionic2, il faut changer le mode de chargement. Il faut passer par une fonction plutôt qu’un chargement direct (ici)

Rebuild.

La traduction fonctionne et la plupart des fonctionnalités également. Par contre, il y un souci dans la navigation “automatique” = quand c’est un component qui gère la redirection. C’est assez bizarre car quand je passe par les liens cela fonctionne sans souci.

selection_036

Après plusieurs tests et recherche, il semble que le souci ne survienne que si l’action fait suite à un submit dans un formulaire. En effet, dans l’application, j’utilise à d’autres endroits le même type de code :

this.router.navigate

et cela fonctionne très bien. Le souci semble venir du fait que l’origine de l’action se trouve dans un formulaire. D’ailleurs si le bouton à l’origine de l’événement est en dehors du formulaire : RAS. Pourquoi je sais pas et je cherche encore.

Dernier build

Après le déplacement des différents boutons, l’ensemble de l’application est fonctionnelle !

Bilan de la 1/2 journée

Objectifs atteints ! Bon, j’ai pas vraiment exploré autant Cordova que je le voudrais : l’intégration de l’application Angular 2 m’a pris pas mal de temps. Mais j’ai appris pas mal de choses sur Docker, Angular 2 & (quand même Cordova). J’ai droit à une demi-bière !

Liens