· Tech watch

Android Lollipop : quoi de neuf pour les développeurs ?

La nouvelle version d’Android, Android Lollipop, a été annoncée lors de la conférence Google I/O en juin 2014. Cet article présente les principales nouveautés de la version preview du SDK pour smartphone et tablette. Il se base sur la documentation fournie par Google et sur le développement d’une application pour expérimenter ces nouveautés. Comme il s’agit d’une preview, certaines parties de l’API sont amenées à être modifiées dans un avenir proche.

Material Design

Présenté en même temps qu’Android Lollipop, Material Design est un langage de conception qui donne des lignes directives aux concepteurs et aux designers dans le but d’unifier les interfaces entre les applications et entre les différents supports (smartphones, tablettes, PC, montres connectées, …).

Avec la nouvelle version d’Android, Google fournit aux développeurs d’applications des outils pour suivre les règles données par Material Design.

Thème

Un nouveau thème est introduit avec Android Lollipop, simplement nommé Material. Ce thème apporte des animations de transition entre les activités, des effets lors des interactions avec les contrôles utilisateurs par défaut (checkbox, textview, …) et une palette de couleurs personnalisable. Cette palette est utilisée par le système pour les couleurs de l’ActionBar et des contrôles utilisateurs notamment.

Thème Material avec une palette de couleurs personnalisée
Thème Material avec une palette de couleurs personnalisée

Animations

L’une des nouveautés clefs liée au Material Design est l’introduction de nouvelles animations, notamment lors d’interactions de l’utilisateur. Le SDK Android Lollipop permet d’ajouter et de personnaliser simplement différent types d’animations :

  • l’animation d’ondulation lors du clic sur une vue
  • l’animation d’apparition d’une vue
  • les transitions entre les activités

Ondulation

Lors du clic sur une vue, un effet visuel informe l’utilisateur de l’endroit où il a cliqué. Avec Android Lollipop, l’animation par défaut lors du clic sur un bouton est un effet d’ondulation qui se propage, comme illustré ci-dessous.

Effet d’ondulation lors du clic
Effet d’ondulation lors du clic

Pour ajouter l’effet d’ondulation sur une vue personnalisée, il faut créer un drawable de type ripple. Ce nouveau type de drawable permet de spécifier le background de la vue pour l’état normal et la couleur de l’ondulation pour l’effet de l’état pressé. Il est également possible de définir un masque pour le cas où la vue ne serait pas rectangulaire.

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
   android:color="?android:colorPrimaryDark">
    <item android:drawable="@drawable/btn_bg_normal"/>
    <item android:id="@android:id/mask" android:drawable="@drawable/btn_bg_normal"/>
</ripple>

Ce drawable doit être attribué au background de la vue.

Apparition

Android Lollipop introduit une nouvelle classe utilitaire, ViewAnimationUtils. Elle permet de créer simplement des animations d’apparition et de disparition de vue. Pour l’instant, seule une animation circulaire est disponible mais d’autres types d’animations seront certainement ajoutés rapidement.

Pour l’utiliser, il suffit de spécifier la vue, les coordonnées du centre du cercle et des angles de départ et d’arrivée :

int cx = (view.getLeft() + view.getRight()) / 2 ;
int cy = (view.getTop() + view.getBottom()) / 2 ;
int finalRadius = view.getWidth() ;
ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius).start() ;

Transition

Jusqu’à présent, la plupart des applications utilisaient les transitions par défaut entre les activités, qui dépendent de l’appareil et de la version d’Android. Android Lollipop simplifie la mise en place d’une animation personnalisée pour l’entrée et la sortie d’une activité grâce aux méthodes setEnterTransition et setExitTransition. Pour l’instant, trois types d’animations d’entrée ou de sortie d’écrans sont disponibles : fondu, glissement et explosion.

Mais la principale nouveauté sur les transitions d’écrans est l’ajout d’éléments partagés entre deux activités. Par exemple, si une même image est présente sur les deux activités à une position différente et avec une taille différente, la transition effectuera une translation et un redimensionnement de l’image.

Pour indiquer à chaque activité qu’il s’agit de la même image, il faut que l’attribut viewName des deux composants images ait la même valeur. Lors du lancement de la seconde activité, il faut ajouter des options pour spécifier l’élément partagé.

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
imageView, "img") ;
startActivity(new Intent(this, SecondActivity.class), options.toBundle()) ;
Transition entre deux activités ayant une image comme élément partagé
Transition entre deux activités ayant une image comme élément partagé

Il est possible d’avoir plusieurs éléments partagés. Dans ce cas, il faut définir l’attribut viewName pour chaque élément et le spécifier dans les options :

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "name1"),
        Pair.create(view2, "name2")) ;

Ombre

Une nouvelle propriété pour les vues est introduite avec Android Lollipop, l’élévation. Elle correspond à la coordonnée Z d’une vue et simplifie l’ajout d’une ombre à cette vue. En effet, il suffit de définir une élévation et un background et l’ombre appropriée sera ajoutée automatiquement.

L’ombre peut être utilisée dans des animations pour surélever temporairement la vue. Pour cela, il faut utiliser la nouvelle méthode {translationZ} de la classe ViewPropertyAnimator.

Malheureusement, toutes ces nouveautés liées au Material Design sont disponibles uniquement sur Android Lollipop.

Nouveaux widgets

Deux nouveaux widgets font leur apparition avec Android Lollipop. Ils sont disponibles dans la librairie de support v7 et peuvent donc être utilisés à partir d’Android 2.1.

Recycler View

Il s’agit d’un conteneur pour un grand nombre de vues. Ces vues peuvent être recyclées ce qui permet un défilement plus fluide. Ce widget est le successeur de la ListView.

Jusqu’à présent, afin d’améliorer les performances des listes, il fallait utiliser le pattern ViewHolder, c’est-à-dire créer une classe chargée de garder les références des vues utilisées pour les éléments de la liste. Ce pattern évite d’appeler plusieurs fois la méthode findViewById pour récupérer la référence d’une vue rendant le défilement de la liste plus fluide. L’utilisation de ce pattern est considéré comme une bonne pratique mais elle n’est pas obligatoire.

Pour rappel, avec une ListView classique et un adapter personnalisé, il faut surcharger la méthode getView :

@Override
public View getView(int i, View convertView, ViewGroup parent) {
ViewHolder holder ;
       if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false) ;
            holder = new ViewHolder() ;
            holder.content = (TextView) convertView.findViewById(R.id.content) ;
            convertView.setTag(holder) ;
        } else {
            holder = (ViewHolder) convertView.getTag() ;
        }
        holder.content.setText(dataset.get(i) ;
        return convertView ;
}

RecyclerView introduit un nouveau type d’adapter, RecyclerView.Adapter, qui requiert l’utilisation d’un ViewHolder. Il faut d’abord créer le ViewHolder qui se charge d’appeler findViewById :

public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView content ;
        public ViewHolder(final View convertView) {
            super(convertView) ;
            content = (TextView) convertView.findViewById(R.id.content) ;
        }
}

La méthode getView est remplacée par deux méthodes, l’une pour inflater la vue et son ViewHolder et l’autre pour lier les données à la vue.

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false) ;
        return new ViewHolder(v) ;
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
        holder.content.setText(dataset.get(i)) ;
}

Par ailleurs, le widget RecyclerView gère également les animations pour l’ajout, la suppression ou le déplacement d’éléments dans la liste. Lors d’une modification de la liste de données, il faut spécifier précisément à l’adapter le type de modification. Pour cela, les nouvelles méthodes de l’adapter notifyItemInserted, notifyItemRemoved et notifyItemChanged doivent être appelée plutôt que notifyDataSetChanged. Les animations par défaut peuvent être remplacées par des animations complètement personnalisées.

Enfin, RecyclerView permet de réaliser des listes et des grilles avec un défilement vertical ou horizontal.

Pour résumer, le widget RecyclerView est une version plus avancée et plus flexible de la ListView, avec un recyclage plus efficace.

CardView

C’est un nouveau layout qui permet d’afficher des informations à l’intérieur de cartes. Ces cartes ont un aspect homogène quelle que soit l’application.

Android Runtime

Android Runtime (ART) est un moteur d’exécution apparu avec Android KitKat pour remplacer Dalvik. Sur KitKat, il fallait aller dans les options pour développeurs pour l’activer. Avec Android Lollipop, ART sera utilisé par défaut à la place de Dalvik.

La principale nouveauté d’ART est la compilation AOT (ahead-of-time). Elle consiste à effectuer la compilation d’une application avant son exécution, contrairement à la compilation JIT (just in time), utilisée par Dalvik, qui compile le code à la volée pendant l’exécution. ART compile une application une seule fois, pendant son installation. Cela permet d’avoir de meilleures performances lors de l’exécution de l’application et de réduire l’utilisation du processeur.

La plupart des applications existantes devraient fonctionner sous ART sans modification. Toutefois, certains problèmes peuvent apparaître dans des cas spécifiques comme lors de l’utilisation d’une JNI (Java Native Interface) afin d’inclure du code C/C++.

Notifications

Le système de notifications connaît quelques modifications avec l’arrivée d’Android Lollipop. Le design des notifications a été revu afin de se conformer au Material Design. Les notifications sont désormais synchronisées dans le cloud, ce qui permet d’afficher une notification sur tous les devices sur lequel un utilisateur est connecté.

Elles sont également envoyées par défaut aux appareils Android Wear. Les développeurs peuvent contrôler les notifications qui sont envoyées et l’action à réaliser au clic sur la notification.

Nouveau design des notifications, notifications sur l’écran de dévérouillage et heads-up notification
Nouveau design des notifications, notifications sur l’écran de dévérouillage et heads-up notification

Les notifications sont désormais affichées sur l’écran de déverrouillage. Cela peut poser un problème de confidentialité, puisque des informations sensibles de l’utilisateur peuvent se retrouver accessibles à quiconque allume l’écran de l’appareil. Afin de palier ce problème, une notion de niveau de visibilité a été ajouté. L’utilisateur peut choisir dans les options quel niveau de visibilité est affiché sur l’écran de déverrouillage. Ce niveau peut prendre les valeurs suivantes :

  • public : affiche le contenu intégral de la notification, c’est la valeur par défaut,
  • privé : affiche uniquement des informations basiques telles que l’icône et le nom de l’application, il est possible de redéfinir le contenu de la notification affichée dans ce cas plutôt que d’utiliser celui par défaut,
  • secret : affiche le minimum d’information.

Par ailleurs, des métadonnées peuvent être associées à une notification. Elles sont utilisées par le système pour trier, filtrer et regrouper les notifications. Elles sont à déterminer lors de la création de la notification et permettent de définir :

  • une catégorie : par exemple appel entrant ou alarme,
  • une priorité : une notification avec une priorité haute sera affichée en tant que “heads-up notification” c’est-à-dire au dessus de l’application courante, même s’il s’agit d’une application en plein écran ou d’un jeu
  • une personne ou un ensemble de personnes : par exemple pour grouper les notifications pour une même personne.

Et aussi…

En plus des nouveautés présentées dans cet article, Android Lollipop apporte aussi de nombreux ajouts et modifications sur certaines fonctionnalités spécifiques de l’API. Par exemple, des améliorations ont été apportées à la gestion de la caméra ou de la connectivité.

Cet article se concentre uniquement sur les nouveautés apportées par Android Lollipop sur smartphone et tablette. Mais Android Lollipop permet également de développer des applications pour Android Wear ou Android TV. Et Google ne compte pas s’arrêter là puisque Android Fit et Android Auto ont aussi été présentés lors de la conférence Google I/O 2014.