Application mobile Cordova avec Meteor

Cet article fait suite à l’article Meteor, pour un développement plus rapide qu’une fusée.

J’ai décidé de m’attaquer à la partie mobile proposée par le framework. Il est en effet possible depuis la version 1.0 de créer des applications via Cordova. Je vous propose d’adapter l’application JoliSnap réalisée dans mon article précédent.

Pour ajouter le support du mobile, il suffit de trois commandes

 $ meteor add-platform ios
 $ meteor add-platform android

Puis lancer l’application avec la commande

 $ meteor run ios

First launch

On voit que l’adaptation responsive fonctionne mais n’est pas prévue pour cette taille d’écran (scrollbar horizontale). De plus il est impossible de prendre des photos avec l’API HTML5.

Nous allons donc améliorer notre application en utilisant le framework CSS Ionic et Cordova pour créer une application mobile hybride. À l’aide du système de build de Meteor, nous pourrons ainsi compiler une application publiable sur les stores android et iOS.

Architecture

J’ai préféré éviter la création d’une nouvelle application pour la version mobile, afin de garder le maximum de code entre la version desktop et mobile. Il est possible de séparer le code avec la constante Meteor.isCordova mais pour éviter l’inclusion des librairies de chaque côté, j’ai créé deux packages.

 $ mkdir packages && cd packages
 $ meteor create --package app-mobile
 $ meteor create --package app-desktop
 $ cd ..
 $ meteor add app-mobile
 $ meteor add app-desktop

Le problème d’un package est qu’il faut définir à la main chaque fichier à inclure pour le serveur, le client ou le mobile. Il faut aussi rajouter la liste des packages dont nous dépendons. Ce qui donne pour le package app-mobile :

Package.describe({
  name: 'app-mobile',
  version: '0.0.1',
  summary: 'JoliSnap mobile files'
});

// api.use to list packages needed
// api.addFiles to list files used for each platform
Package.onUse(function(api) {
  api.use([
    'meteor-platform',
    'iron:router',
    'fourseven:scss',
    'meteoric:ionic-sass',
    'meteoric:ionicons-sass',
    'meteoric:ionic',
    'meteoric:autoform-ionic'
  ],['web.cordova']);

  api.addFiles([
    'views/mobile.html',
    'router.js',
    'jolisnap.js',
    'stylesheet/mobile.scss'
  ],['web.cordova']);
});

Bien que fastidieux, cela nous permet de mieux comprendre de quoi dépend notre code !

Prendre des photos

Il faut ensuite ajouter le support du plugin Cordova « camera ». L’API du package mdg:camera rajoute une méthode MeteorCamera.getPicture([options], callback) qui permet de gêrer le processus de récupération d’une photo pour le desktop et le mobile.

Template.form.events({
    'click #takePhoto': function (event, context) {
      event.preventDefault();

      MeteorCamera.getPicture({}, function (error, data) {
        Session.set('photo', data);
        $(event.currentTarget).css('background-image',  'url('+data+')');
      });
    }
  });

enter image description here

On sauvegarde la photo dans l’objet Session pour ensuite la récupérer lors de l’envoi du formulaire.

Interface

Pour faciliter l’adaptation au mobile et améliorer l’expérience utilisateur, j’ai choisi d’utiliser le framework Ionic. Cette librairie propose de nombreuses vues et styles pour créer une ergonomie mobile proche d’un rendu natif (listes, formulaires, modale…).

Ionic dispose de bindings pour Angular mais grâce au travail de @nwientge, nous disposons d’un package adapté à Meteor ! Il manque encore quelques directives mais les plus importantes sont disponibles et je n’ai rencontré aucun problème pendant l’adaptation de l’application.

 $ meteor add iron:router fourseven:scss meteoric:ionic-sass meteoric:ionicons-sass meteoric:ionic

Ensuite il faut importer les styles de ionic utilisant sass en créant un fichier packages/app-mobile/stylesheet/mobile.scss.

@import '.meteor/local/build/programs/server/assets/packages/meteoric_ionic-sass/ionic';
@import '.meteor/local/build/programs/server/assets/packages/meteoric_ionicons-sass/ionicons';

Je me suis beaucoup inspiré des applications d’exemple proposées sur le dépôt de Meteoric car la documentation n’est pas suffisante pour le moment. Deux nouvelles vues ont été rajoutées par rapport à la version desktop et l’accueil a été transformé en simple liste.

Vue photo

Cette vue représente une seule photo avec le nom de l’auteur et la date d’ajout.

Nous utilisons l’héritage de templates pour surcharger le titre présent dans la barre de navigation, ou encore ajouter un bouton de retour vers la vue liste.

Les tags de type {{#ion*}} sont des blocs de contenu correspondant à du code Ionic. Pour avoir une meilleure idée du code qui va être généré il faut aller lire les templates définis dans le package meteoric:ionic sur github (par exemple pour le template ionContent).

<template name="mobilePhotosShow">
    {{#contentFor "headerButtonLeft"}}
        {{>ionNavBackButton path="mobile" text="JoliSnap"}}
    {{/contentFor}}

    {{#contentFor "headerTitle"}}
        <h1 class="title">Photo</h1>
    {{/contentFor}}

    {{#ionView}}
        {{#ionContent class="padding photo-detail"}}
            {{#with photo}}
                <div class="card">
                    <div class="item item-divider">
                        <h2>{{name}}</h2>
                        <p>{{formatTime createdAt}}</p>
                    </div>
                    <div class="item item-image">
                        <img src="{{url}}">
                    </div>
                </div>
            {{/with}}
        {{/ionContent}}
    {{/ionView}}
</template>

Vue formulaire

Cette vue est de type modale, elle va donc s’ouvrir au dessus de la vue courante (la liste des photos) et proposer un formulaire et la prise d’une photo via la caméra du device. On peut passer des paramètres lors de l’appel du template, comme ici pour focusFirstInput, pour forcer le focus sur le premier champ de formulaire et éviter à l’utilisateur de devoir le sélectionner à la main.

<template name="mobileForm">
    {{#ionModal focusFirstInput=true customTemplate=true}}
    <div class="bar bar-header bar-stable">
        <button data-dismiss="modal" type="button" class="button button-clear">Cancel</button>
        <h2 class="title">Add a snap</h2>
        <button type="submit" class="button button-positive button-clear">Add</button>
    </div>
    <div class="content has-header">
        {{> quickForm collection="Photos" id="photoForm" type="insert" omitFields="url,createdAt"}}
    </div>
{{/ionModal}}
</template>

J’ai utilisé le package autoform pour faciliter la création et la validation du formulaire. Il suffit d’attacher au préalable un schéma à la collection Photos. Ce code est partagé entre le mobile et le desktop et est aussi présent sur le serveur, ce qui permet d’avoir une validation des données commune.

Photos = new Mongo.Collection("photos");
Photos.attachSchema(new SimpleSchema({
  name: {
    type: String,
    label: "Name",
    max: 200
  },
  email: {
    type: String,
    regEx: SimpleSchema.RegEx.Email,
    label: "Email"
  },
  url: {
    type: String,
    label: "Photo"
  },
  createdAt: {
    type: Date
  }
}));

Petite spécificité pour la version mobile, il faut modifier le template par défaut du formulaire pour rajouter les styles de Ionic.

Meteor.startup(function () {
  AutoForm.setDefaultTemplate('ionic');
});

Debug

Afin de simplifier au maximum le debug au démarrage du projet, l’approche consiste à utiliser le navigateur Desktop en changeant les plateformes du package app-mobile pour web.browser. C’est d’autant plus vrai qu’il existe maintenant des outils de développement qui permettent de simuler des tailles d’écran spécifique ou des lenteurs réseaux.

Pour être plus spécifique au niveau du mobile, je conseille d’utiliser ensuite le « remote debugging » avec Safari pour le simulateur iOS ou celui de chrome pour Android.

Remote debug with Safari

Vous trouverez plus d’informations sur le debug dans la documentation de Phonegap.

Ajout d’un plugin Cordova

L’ajout d’un plugin est très simple, il suffit de rajouter le nom et la version de celui-ci dans le fichier packages/app-mobile/package.js et Meteor va le télécharger automatiquement.

Cordova.depends({
  "org.apache.cordova.statusbar": "0.1.10"
});

Ce sont les plugins de la famille org.apache.cordova qui vont rajouter les fonctionnalités « natives » à votre application (géolocalisation, caméra, stockage interne…) donc n’hésitez pas à les utiliser. La liste est disponible sur le site des plugins Cordova.

Publication

Création des assets

J’ai généré l’ensemble des icônes avec le service ticons créé par Fokke Zandbergen et que nous utilisons habituellement pour nos applications Titanium.

L’étape la plus fastidieuse est le renommage des assets…

App.icons({
  'iphone': 'resources/icons/iphone.png',
  ...
});

App.launchScreens({
  'iphone': 'resources/splash/iphone.png',
  ...
});

Envoi sur le store

Quand votre application est terminée et testée sur device, il reste à la préparer pour l’envoyer sur le store. La procédure complète (build et signature) est détaillée sur le wiki de Meteor1

Il est intéressant de voir que la commande de build nous crée bien un projet Android et un projet Xcode. Cela peut être pratique si l’on souhaite un debug plus proche du natif et de Cordova.

Mise à jour

Fonctionnalité intéressante grâce à Meteor, la mise à jour du code se fait automatiquement lors du déploiement. L’application mobile va télécharger et mettre en cache la nouvelle version du code, se relancer automatiquement2.

Cependant, pour la mise à jour de plugins natifs Cordova, il est nécessaire de refaire une publication sur les stores. De manière générale lors de l’ajout de fonctionnalités importante ou de correction de bug, il est conseillé de faire une mise à jour via le store, ce qui permet de fournir la description des changements apportés à l’utilisateur (et en plus ça donne l’impression à l’utilisateur que l’application « bouge » et que ce n’est pas un projet mort qui n’a pas évolué depuis longtemps).

Conclusion et problèmes rencontrés

L’adaptation a été rapide (environ une journée de travail). Je n’ai pas eu besoin de connaissances approfondies de Cordova, mais cela a demandé quand même plusieurs recherches. En effet, la documentation de la partie mobile n’est pas complète et il est nécessaire d’avoir une vision d’ensemble des technologies qui sont utilisées (Cordova, build isomorphique, séparation en packages…) pour bien s’y retrouver.

Il y a encore beaucoup de travail à effectuer sur les packages isomorphiques avant que ce soit réellement exploitable à grande échelle, en production. Par exemple mdg:camera ne supporte pas la récupération d’une photo dans la galerie, ce qui est assez limitant.

Le manque de documentation se fait également ressentir au niveau de l’adaptation Meteor de Ionic, mais le projet est encore très jeune, actif et très prometteur.

Si vous êtes équipé d’un smartphone Android, vous pouvez tester l’application que nous avons publiée sur l’Android Play! Store !

Screenshots

Ressources


  1. voir https://github.com/meteor/meteor/wiki/How-to-submit-your-Android-app-to-Play-Store 

  2. voir https://github.com/meteor/meteor/wiki/Meteor-Cordova-Phonegap-integration#hot-code-push 

blog comments powered by Disqus