Android 4.4 : l’OS tout terrain de Google ?

Voici le retour de Christine, notre experte Android qui a su jouer de ruse pour décrocher une place au Google Developper Group du jeudi 7 novembre dernier. Il y était présenté le nouveau Android 4.4 qui présente une rupture à plusieurs égards avec les versions précédentes de l’OS mobile.

1. Unification du moteur WebView et du code Chrome mobile.

D’un point de vue développeur, c’est une information majeure :

  • le moteur de rendu des applications hybrides en HTML5 (créées avec phonegap par exemple) bénéficiera des innovations qui sont continuellement apportées au navigateur: homogénéité des rendus, respect des standards, performance…,
  • le développement sera facilité avec la possibilité de déboguer une WebView de la même manière qu’avec Chrome Mobile : à distance, depuis sont Navigateur Chrome et ses fonctionnalités de profilage, modification à chaud du DOM, analyse des erreurs, ajustements CSS en direct etc…

2. l’apparition du Storage Access Framework :

C’est un ensemble des providers standards pour accéder/manipuler plus facilement dans les applications les documents, images, videos etc de l’utilisateur, qu’ils soient stockés sur le Cloud ou dans la carte SD du téléphone. C’est un équivalent unifié du « Parcourir » pour chercher un fichier, sous forme d’un menu latéral.

3. Les objets connectés : tout se met en pllace

  • Framework pour l’impression via WiFi, que ce soit vers le service Google Cloud Print ou vers certaines imprimantes physiques, avec génération du document en PDF.
  • Nouveau sensor pour compter les pas de l’utilisateur
  • Amélioration du NFC

4. Ergonomie, fluidité…

  • Apparition d’un mode « Immersion » pour un affichage total en plein écran, qui cache la barre de notifications en haut et la barre de navigation du bas. De plus, ces éléments peuvent maintenant être rendus translucides
  • Evocation d’un framework de transitions/animations entre les vues pour créer des « scènes » : nous n’avons pas eu de démonstration malheureusement, donc je ne sais pas vraiment ce que ça peut donner
  • Screen recording, pratique pour filmer des tutoriaux,
  • API/Provider pour les SMS/MMS

5. Au coeur du système

Pour les outils de débug, ajout de Proc Stats pour analyser plus finement l’utilisation de la mémoire par les applications.

En plus des optimisations qu’ils ont faites dans le système, le nouveau runtime « ART » qui remplacera Dalvik a été évoqué. On pourra basculer sur ce dernier dans Android 4.4 pour voir ce que ça donne et les développeurs sont d’ailleurs invités à remonter les bugs, comme c’est encore à l’état expérimental.

Des nouveautés très prometteuses donc, il reste à voir ce qui sera au final porté sur les versions antérieures via la Support Library…

En gros, la présentation reprenait tous les points de la release note de Kitkat (http://developer.android.com/about/versions/kitkat.html ), mais en beaucoup plus divertissant, speakers de marque oblige ! (Pour les chanceux : Il parait que la même présentation sera donnée à Devoxx en Belgique dans quelques jours… )

La 2ème présentation un peu plus technique abordait l’image processing sous Android, notamment avec RenderScript qui a réputation d’être assez obscur car peu documenté, mais qui serait très efficace apparemment.
Le code source de l’éditeur de photos stock d’Android 4.4 qui était pris en exemple serait disponible sur AOSP.

Google met un coup d’accélérateur très marqué pour enrichir son OS et fait une place plus importante encore aux développements HTML5. La convergence entre Android et ChromeOS est vraisemblablement dans le viseur.

A bientôt pour des prototypes intégrants ces nouvelles avancées.



AngularJS, premiers pas vers des applications HTML riches

On a entrevu ici les raisons pour lesquelles le JavaScript devient une technologie incontournable et que les besoins de structuration du code expliquent en grande partie l’engouement pour BackboneJS, EmberJS ou AngularJS.

Infotel a réalisé à ce jour plusieurs projets AngularJS qui nous donnent l’occasion de partager quelques bonnes pratiques et retour d’expérience glanés. Ce premier article présente les concepts généraux ainsi que les subtilités des directives pour maîtriser parfaitement l’affichage d’informations et les animations avancées.

présentation graphique et fluide en AngularJS

CRUD - Gestion Back Office en AngularJS

Pourquoi utiliser AngularJS ?

  • AngularJS fonctionne sur le principe MVC (Modèle-Vue-Contrôleur) et apporte aux applications web côté client les services traditionnellement apportés côté serveur, comme les contrôleurs de vues. En conséquence, une bonne partie du fardeau supporté par le back-end est supprimée, ce qui conduit à des applications web plus légères.
  • Le « Data binding » ou couplage des données est un des points fort d’AngularJS. Il permet de relier la vue aux modèles de données et de permettre une mise à jour automatique des changements dans les deux sens : des changements de la vue mettent à jour le modèle et inversement. Ainsi les manipulations du DOM deviennent (quasi) transparentes pour le développeur

Exemple :

<input type="text" ng-model="yourName" placeholder="Enter a name here">
<h1>Hello {{yourName}}!</h1>

Le modèle « yourName » contiendra la valeur entrée dans le champ de texte input. Le « binding » ou couplage au niveau de l’affichage s’effectue via l’opérateur {{ }} qui affiche le texte entré à la volée. Si l’on modifie le champ le modèle se met à jour automatiquement ainsi que la vue.

• Les Contrôleurs peuvent être déclarés sur n’importe quel élément du DOM et permettent de s’occuper de la logique de traitement (réception ou envoi de données vers le serveur par exemple, remplissage d’une liste ou d’un tableau…). L’avantage est que ces manipulations sont découplées de la vue et s’effectuent dans des fichiers séparés permettant une meilleure lisibilité entre la logique métier et la vue.

• Le routage entre différentes vues de l’application est assuré et géré par AngularJS ce qui économise ce travail sur le serveur. Cela permet la réalisation de SPA (Single Page Application) avec plusieurs vues sans harcelé le serveur pour chaque vues.

• La communication avec le serveur est grandement facilitée par les Services. AngularJS propose directement des méthodes pour le CRUD (Create-Read-Update-Delete) sous forme de requêtes XHR(XMLHttpRequest) pour l’insertion, suppression et modification avec une gestion des exceptions en fonction de la réponse du serveur, le tout de façon asynchrone.

• Les directives sont une fonctionnalité unique d’AngularJS et un gros point fort dans la création de composants à insérer dans le DOM. Par exemple il est possible de créer une directive qui s’occupe d’afficher un slider d’images :
HTML : Plus lisible, la directive semble étendre les propriétés de base de l’HTML

La directive n’est pas montrée intégralement ici car nous verrons plus en détails comment les utiliser. L’avantage de ce type de déclaration est double : meilleure lisibilité du DOM et composant réutilisable.
RQ : La directive s’appelle imageSlider mais dans le HTML il faut remplacer les majuscules et elle devient (Autre exemple : LeNomDuneDirective devient le-nom-dune-directive quand elle est utilisé dans le DOM).
• Injection de dépendances : AngularJS permet l’injection de services ou d’objets directement dans le contrôleur ou les directives ce qui réduit également la gestion de cet aspect par le programmeur.
Résumons les principales fonctionnalités d’AngularJS par un schéma :

Rôle des composants Angular

On abordera une prochaine fois la structuration du projet, les rôles des contrôleurs et service, mais nous allons détailler ici le rôle et le fonctionnement des directives (et cela peut-être subtile) :

Les directives
Les directives sont un des éléments phare d’AngularJS car elles distinguent le framework des autres. Nous allons voir comment écrire une directive dans AngularJS.
Pour écrire des directives on déclare un module ‘infotelDirectives’ dans directives.js (qu’on a déjà configuré dans app.js)

angular.module('infotelDirectives', [])
.directive(....) // 1ère  directive
.directive(....) // 2nde directive

Voici un des plus simples exemples de directives: On déclare un nom pour la directive (« blink ») et on lui demande de retourner un template HTML. En l’occurrence on retourne une balise <marquee> qui permet de faire défiler du texte, avec un scrollamount de 100% qui donne l’impression que le texte clignote.

.directive('blink', function() {
  return {
    template: '<marquee scrollamount="100%">Blink!</marquee>'
  };
});

On peut alors utiliser la directive où bon nous semble :

<div blink></div>

Qui devient :

<marquee scrollamount="100%">Blink!</marquee>
Blink!

Resctrict :
Si l’on souhaite utiliser la directive autrement que comme un attribut on doit le signaler avec restrict :

E : element : <blink></blink>
A (par défaut) : attribut : <div blink></div>
C : class : <div class="blink"></div>
M: commentaire : <!– directive: blink –>

.directive('blink', function() {
  return {
    restrict: ‘E,A’, // Ici on ne peut l’utiliser que comme elem ou attr
    template: '<marquee scrollamount="100%">Blink!</marquee>'
  };
});

Transclude :

Si l’on souhaite placer le texte (« Blink ! ») dans le DOM et que le template l’entoure on doit utiliser la transclusion :

.directive('blink', function() {
  return {
    restrict: ‘E,A’, // Ici on ne peut l’utiliser que comme elem ou attr
    template: '<marquee scrollamount="100%" ng-transclude></marquee>',
  };
});

HTML :

Texte placé dans le DOM et non plus dans le template de la directive

Qui devient :

<marquee scrollamount="100%"> Texte placé dans le DOM et non plus dans le template de la directive </marquee>
Texte placé dans le DOM et non plus dans le template de la directive

NgTransclude sert à placer les éléments qui se trouve entre <blink> et </blink> dans le DOM à l’emplacement précisé par ng-transclude.

Declarer le template dans un fichier séparé

Il est également possible de remplacer la déclaration du template par un fichier qui contiendra le bout de HTML a cloné dans le DOM. Dans ce cas il faut utiliser templateUrl.

temp.html :

<marquee scrollamount="100%" ng-transclude></marquee>

Directive :

.directive('blink', function() {
  return {
    restrict: ‘E,A’, // Ici on ne peut l’utiliser que comme elem ou attr
    templateUrl: chemin/vers/le/fichier/temp.html
 
  };
});

Fonction link :

Une fois que le template a été cloné dans le DOM, la fonction link est exécutée. C’est dans cette fonction que la plupart de la logique de la directive se trouve.
Il y a trois éléments à passer à la fonction link :

<div blink attr1=’attribut1’ attr2=’attr2’></div>

• scope : un objet scope pour manipuler des modèles de la directive
• element : l’élément sur lequel la directive est appliquée (le div)
• attributes : les attributs de l’élément accessible comme un objet (on accède à attr1 via attributes.attr1 etc.)

Par exemple si l’on désire effectuer un ng-click sur le texte clignotant et obtenir un champ de texte à la place on peut masquer le texte et montrer le champ input. Cela se réalise avec les directives NgShow et NgHide.

.directive('blink', function() {
  return {
    restrict: ‘E,A’,
    template: '
<div><marquee ng-click="edit()" ng-hide="editMode" ' +
              'scrollamount="100%" ng-transclude></marquee> ' +
              '
<input type="text" ng-show="editMode" ></div>
 
',
  link: function(scope, element, attrs) {
      // le booléen editMode contrôle la visibilité de blink et de input
      scope.editMode = false; // initialement
      // appellé quand la balise marquee est cliquée
      scope.edit = function() {
          scope.editMode = true; // toggle le texte ou le champ
      };
    }
 
 };
});

ng-hide=true : masqué, ng-show=true : visible | ng-hide=false : visible, ng-show=false : masqué
Afin de permettre la modification du texte affiché par le champ input on attache un événement « blur » (le contraire de focus) pour signaler au marquee de modifier son texte quand on quitte le champ input.

Il faut appeler $apply pour signaler à la vue de se mettre à jour :

.directive('blink', function() {
  return {
    restrict: E,A,
    template: '
<div><marquee ng-click="edit()" ng-hide="editMode" ' +
              'scrollamount="100%" ng-transclude></marquee> ' +
              '
<input type="text" ng-show="editMode" ></div>
 
',
  link: function(scope, element, attrs) {
 
// sélectionner les éléments du template : angular.js embarque jqlite, une version minimale de jquery qui permet d’utiliser les sélecteurs usuelles de Jquery
var marquee = element.find("marquee");
var input = element.find("input");
 
// attacher un évenement blur (perte de focus) au input
      input.bind('blur', function() {
// Si on n’utilise pas $apply, la vue ne sera pas au courant de la transformation
        scope.$apply(function() {
          // masquer le champ input et montrer le texte du marquee
          scope.editMode = false;
          // mettre à jour le champ du marquee
          marquee.text(input.val());
        });
      });
      // le booléen editMode contrôle la visibilité du texte blink et du input
      scope.editMode = false; // initialement
      // appellé quand la balise marquee est cliqué
      scope.edit = function() {
          scope.editMode = true; // toggle le texte ou le champ
      };
    }
 
 };
});

Directives ImageSlider: le casse-tête final !
Voyons un autre exemple faisant intervenir un composant écrit pour Jquery. Il s’agit de bxslider.js, un slider d’images. En réalité, on a utilisé deux directives pour que le composant s’initialise correctement :
La première directive s’appelle « imageSlider » :
On crée un template pour notre slider. Il doit déclarer la classe « bxslider » sur un <ul> et les images doivent être associées dans les

  • suivant.

       .directive("imageSlider", function() {
        return {
            restrict: 'E',
            replace: true,// signifie que l’on remplace la balise par le template
             scope: {
                image: '=' // déclare un attribut image, dans le dom on passera à cet                          //attribut la source de données contenant les chemins d’images :
        //<image-slide image=“projet.imagesSet”></image-slide>
            },
            template: '
    <ul class="bxslider">'+
                      '
    <li check-last ng-repeat="slide in image">'+
                      '<a ng-click="open(slide.chemin)" href="">'+
                      '<img ng-src="image/{{slide.chemin}}" alt="image non disponible : {{slide.chemin}}" title="{{slide.chemin}}" class="imageSlide">'+
                      '</a>'+
                      '</li>
     
    '+
                      '</ul>
     
    '
        };
    })

    On utilise ng-repeat pour ajouter des diapositives dans chaque li. Chaque « slide » provient de projet.imagesSet , qui correspond au modèle contenant les chemins d’images. On obtient ce modèle via la déclaration scope :{image : ‘=’} qui spécifie que la valeur de scope.image sera égale à la valeur du modèle que l’on passe à l’attribut image dans la directive <image-slider image="modele"> (en l’occurrence « modele » sera projet.imagesSet).

    On veut également mettre en place une fonction qui permet d’afficher l’image dans une fenêtre modale en cliquant dessus (« open » qui est définit dans le contrôleur). Mais l’utilisation d’un ng-repeat dans le template est problématique car si l’on essaye d’initialiser le plugin directement dans la fonction link de cette directive cela ne fonctionne pas. Il semble que l’exécution du NgRepeat ne soit pas terminée au moment où l’on appelle la fonction link.
    L’idée est donc d’appeler une autre directive « checkLast » sur chaque <li> qui vérifie s’il s’agit du dernier élément de la boucle et si c’est le cas d’initialiser le composant.

            .directive('checkLast', function() {
        return function(scope, element, attrs) {
            if (scope.$last === true) { // s’il s’agit du dernier
    <li> du ng-repeat
                element.ready(function() { // on initialise le composant
                    var bx = $('.bxslider').bxSlider({
                        mode: 'fade', // les options du composant Jquery
                        pager: true
                    });
                })
            }
        }
    })
            }
        }
    });

    Au niveau du DOM on peut alors déclarer le composant et choisir sa source d’images. De plus il est réutilisable :
    <image-slide image="projet.imagesSet"></image-slide>

    Nous aborderons en détail l’appel au services REST, et comment on intègre la gestion du LocalStorage pour booster les performances et fonctionner en mode déconnecté !
    A suivre…



  • Le futur est aux frameworks JavaScript

    …et peut-être à AngularJS

    Au delà du titre provocateur se dessine une des tendances lourdes de la communauté des développeurs Java & Web:l’intérêt croissant pour les Frameworks JavaScript MV* (MVC ou MVVM).

    C’est à première vue très surprenant :

    • Dans notre imaginaire, le JavaScript a souvent été une approche d’enrichissement graphique, intégré plus ou moins maladroitement dans les applications Web,
    • Les frameworks Java on offert des paradigmes très orientés ‘serveur’ masquant l’utilisation de JavaScript, participant à la méconnaissance du langage, a la création d’approches techniques lourdes (parfois maladroites) et quelques effets néfastes en termes de maintenance (http://blogdesexperts.infotel.com/?p=660).

    Mais récemment, plusieurs facteurs concordants plaident pour le retour sur le devant de la scène du JavaScript :

    • La maturation du HTML5 et plus particulièrement des techniques suivantes, qui se font au travers d’instructions JavaScript dédiées:

      o Web Socket –> Temps réel,

      o LocalStorage –> Mis en cache de données et fonctionnement en mode déconnecté,

      o Canvas –> Dessin et animations en 2D et même 3D,

      o Mode déconnecté –> Une grande partie de la logique métier est présente dans le client.

    • L’avènement du mobile, et l’émergence de solutions cross-platform qui poussent encore plus dans cette direction, avec des approches différentes, traduisant l’effervescence de cet eco-systèmes HTML / CSS / JavaScript:

      o Sencha,

      o Titanium,

      o PhoneGAP…

    • Une multiplication des APIs qui renforce la constitution d’applications qui agrègent des services, et plaide de facto pour des clients plus riches,

      o Prenons l’exemple d’un Intranet typé ‘Réseau Social’ qui regrouperait les communications institutionnelles, l’accès au système RH, la gestion de la connaissance, la communication interne

    • La démocratisation d’interfaces enrichies par l’emploi de jQuery (et autres librairies similaires), et l’habitude prise par les utilisateurs de disposer d’une ergonomie soignée et réactive. Ce qui exige de coordonner la constitution des pages

    Et maintenant ?

    Première approche : nous poursuivons la même tactique

    Nous nous reposons sur des frameworks qui vont encapsuler la réalité des traitements dans un langage tiers :

    Deuxième approche : plus proche du Web

    • Retenir des solutions qui se veulent plus proche de l’esprit WEB, laissant une plus grande liberté dans la création d’interfaces : PLAY et Grails par exemple.

    Enfin, le choix de frameworks JavaScripts :

    • Leur rôle est de structurer et recueillir le code de la partie cliente : Ecrans, transition, appels aux services. Sans être limité à cela, c’est un point crucial pour la viabilité de telles approches et éviter le javascript ‘Spaghetti’ inmaintenable qui ne manque pas d’apparaître lorsque les fonctionnalités s’enrichissent.
    • Indirectement, ils adressent (partiellement ou complètement) les problématiques suivantes :

      o Mise à jour du DOM (et des informations affichées à l’écran) lors des changements du modèle (et vice-versa)

      o Application de templates, avec des solutions plus ou moins élégantes,

      o Intégration naturelle de librairies tierces (et en JavaScript elles sont vite innombrables),

      o Testabilité.

    • Ils offrent un bénéfice de productivité immédiat dans le développement des interfaces :

      o Chargement immédiat des modifications (une révolution !),

      o Utilisation productive des extensions Chrome / Firefox de développement (et application des modifications HTML / CSS / JavaScript) opérées,

      o Découplage client serveur ne nécessitant pas la disponibilité de solutions complètes

    Rapide horizon des solutions du moment

    Parmi ceux qui sont aujourd’hui sous le feu des projecteurs, on peut citer Ember.js, Knockout JS, Backbone et AngularJS pour lesquels une comparaison est disponible ici (Elle date de janvier 2012, déjà plusieurs générations sont passées) : http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/ .

    Signe de maturité, on voit des approches qui proposent des solutions cohérentes comme http://resthub.org

    Nos premiers retours d’expérience issus de projets représentatifs (au-delà du simple TodoMVC — http://addyosmani.github.com/todomvc/ — ) ont permis de mettre en évidence des lacunes quasi rédhibitoires (non-maintenabilité et verbosité avec Backbone et Knockout) et de vrais satisfecit avec AngularJS : http://angularjs.org/.

    Ce dernier est une approche véritablement sérieuse, élégante, documentée et accessoirement supporté par Google.

    En quelques points Angular JS propose :

    • Un découpage clair favorisé par injection de dépendance (Contrôleur, Service, …);
    • L’utilisation de ‘directives’ pour créer des composants réutilisables,
    • Un moteur de rendu qui ne dénature pas (trop) le HTML, incluant des fonctions de filtre, de boucle,…
    • Des fonctions de validation de formulaires, de gestion de l’historique,
    • Une extension Chrome (Batarang) qui rend le débogage très efficace,
    • Une testabilité de premier ordre (Cf. testacular),

    Le plus simple est de commencer avec un projet de base bien structuré : https://github.com/angular/angular-seed

    Les inconvénients qui peuvent être avancés à ce jour sont : la mise en place du référencement, une compatibilité avec les navigateurs incomplète (IE 7 et 8 notamment), des compétences encore peu répandues, une adoption encore marginale…mais qui l’est de moins en moins.



    Les librairies JavaScript : la piste JQuery

    Introduction

    L’observation simple que l’on peut faire aujourd’hui est celle d’une attente toujours plus grande en termes d’interactivités et d’ergonomie pour les applications Web. Cette tendance de fond a très largement poussé à l’adoption du JavaScript sous toutes ses formes, que ce soit :

    • Par utilisation de librairies dédiées (MooTools, prototype, JQuery) ;
    • Ou par génération complète (GWT) ou partielle (Wicket, JSF) du client.

    L’adoption de technologies plus abouties pour les interfaces riches, telles Flex ou Silverlight, est restée marginale (du moins, pour le moment) mais se justifie toujours lors de besoins très « pointus ».

    C’est pourquoi, même si les technologies Web standard concèdent toujours un peu de retard dans la richesse des composants, leur résistance s’explique par :

    • La relativement bonne couverture des technologies HTML+JS qui permettent l’enrichissement de « l’expérience utilisateur » ;
    • Il n’existe pas de propriété pour les normes sur lesquelles elles reposent : ce qui ralentit dans un sens leur évolution favorise dans un autre leur propagation et démocratisation ;
    • … l’attentisme, les normes à venir (HTML5, CSS3…) portent en elles un grand nombre de promesses.

    En effet, le HTML5 fournira sous peu la gestion d’objet Canvas (pour la création de graphiques statiques et dynamiques), le cache local, les WebSocket et le mode déconnecté… le tout contrôlé en JavaScript dont le rôle s’en trouvera naturellement renforcé.

    La piste JQuery

    Pour contrôler et organiser ce code, la librairie JQuery se pose en candidat très sérieux. Sa compatibilité étendue avec les navigateurs existants (même les plus réfractaires au respect des normes… n’est-ce pas IE6 ?) ainsi que sa faculté à faciliter le développement de plug-ins expliquent surement le succès non démenti qu’elle connaît depuis bientôt trois ans.
    Elle bénéficie aujourd’hui d’un catalogue fourni et varié dont on peut citer ‘arbitrairement’ quelques exemples :

    • Validation de formulaires ;
    • Drag and drop ;
    • Animation de diaporama, défilement d’informations ;
    • Manipulation de styles ;
    • Gestion de flux rss ;
    • Création de graphiques (histogrammes) et gestion d’agenda ;
    • Appels Ajax et application de modèles (templates) aux données récupérées ;
    • Stockage et recherche de données dans la zone de cache locale…

    Ces exemples témoignent de la diversité des champs d’application des plugins et renforcent la conviction que le JavaScript va supporter de plus en plus de responsabilités dans l’élaboration du client Web.

    Les enjeux et problématiques

    Alors qu’il a été trop longtemps considéré comme une rustine inélégante posée sur les clients Web pour les dynamiser, le JavaScript est devenu une couche à part entière de l’architecture technique des applications Web. On ne peut plus l’ignorer pour concevoir l’application, ni minimiser les compétences nécessaires pour vraiment le maîtriser.

    Preuve de son importance, le JavaScript « s’outille ». On voit ainsi émerger des outils de gestion des dépendances de scripts, des bibliothèques de tests unitaires (QUnit pour JQuery), et bien sûr, des consoles de débogages (FireBug, Chrome ou IE8).

    Toutefois, cette intégration « massive » de code JavaScript dont il faut vérifier la compatibilité avec la majorité des navigateurs du marché (dont ceux en version mobile) requiert une attention particulière lors des tests. C’est dans ce cadre qu’un outil comme SELENIUM devient indispensable pour garantir une couverture de tests d’intégration satisfaisante.