Accueil > Mobile > Android : comment gérer la fragmentation des versions d’API

Android : comment gérer la fragmentation des versions d’API

Android est bien connu pour être un écosystème très fragmenté, tant au niveau du matériel que du logiciel :

  • Ecrans (taille physique – densité – résolution)
  • Capacités (puissance CPU, mémoire, GPU)
  • Architecture matérielle (ARM, Intel)
  • Format de l’appareil : présence d’un clavier physique, orientation naturelle de l’écran…
  • Présence d’une surcouche constructeur
  • Version d’Android

Cela peut rebuter les développeurs débutants, mais avec un peu de pratique c’est facilement gérable. Je vais me concentrer aujourd’hui sur le dernier point, à savoir la fragmentation des versions d’Android, et je vais essayer de vous donner quelques astuces pour que ce ne soit plus un problème.

En premier lieu, faisons le point sur le mode d’évolution de l’API.  Chaque version apporte de nouvelles fonctionnalités, mais aucune fonctionnalité n’est jamais supprimée lors de l’arrivée d’une nouvelle version. Au pire, certaines passent en deprecated, mais elles restent utilisables. La conséquence de cela est que les applications écrites pour une API version N sera automatiquement compatible avec l’API N+1, N+2, N+3, etc. (principe de retrocompatibilité). En pratique, le passage à une nouvelle version peut poser quelques problèmes à cause d’effets de bords, mais ils sont généralement facile à résoudre. Le seul vrai problème qui se pose, c’est lorsqu’on veut utiliser des fonctionnalités récente qui n’existent qu’à partir d’une certaine version de l’API. Dans ce cas il faut faire des choix :

  • ne plus supporter les versions d’API précédentes,
  • ne pas utiliser ces fonctionnalités,
  • ou bien faire le compromis entre les deux, à savoir adapter le comportement de l’application en fonction de la version détectée au runtime.

En pratique il faudra faire un mélange des trois :-) car pour chaque fonctionnalité le pour et le contre doit être pesé.

Pour commencer, il faut se renseigner sur les chiffres. Des statistiques sur la distribution des versions sont mises à jour toutes les deux semaines et sont disponibles à cette adresse : http://developer.android.com/about/dashboards/index.html. C’est une bonne aide à la décision. Il faut être pragmatique : ne pas hésiter à retirer le support des vieilles versions qui ne sont quasiment plus utilisées. La perte d’utilisateurs potentiels et légère, et le gain en terme de disponibilité d’API est forcément intéressant. Comme il sort en moyenne une nouvelle version tous les 6 mois, il peut être judicieux de se poser la question du retrait d’une vieille version tous les 6 mois également.

Version Codename API Distribution
1.5 Cupcake 3 0.1%
1.6 Donut 4 0.4%
2.1 Eclair 7 3.4%
2.2 Froyo 8 12.9%
2.3 – 2.3.2 Gingerbread 9 0.3%
2.3.3 – 2.3.7 10 55.5%
3.1 Honeycomb 12 0.4%
3.2 13 1.5%
4.0.3 – 4.0.4 Ice Cream Sandwich 15 23.7%
4.1 Jelly Bean 16 1.8%

Source : http://developer.android.com (01/10/2012)

A l’heure où j’écris ces lignes, les versions 1.5 et 1.6 ne constituent que 0.5% des appareils en circulation. Il me semblerait pertinent de ne plus les supporter, mais c’est aussi une décision marketing qui va dépendre d’autres facteurs.

Mais revenons à ce que j’ai déclaré plus haut : il est possible d’adapter le comportement de l’application en fonction de la version détectée. Cela permet, dans la même application, d’utiliser des fonctionnalités récentes lorsque celles-ci sont disponibles, et de se rabattre sur un fonctionnement plus simple si la fonction n’est pas disponible. Pour pouvoir faire cela, il faut juste respecter un principe simple : lorsqu’une classe de notre application va être utilisée, elle est chargée et vérifiée par la VM, et si dans cette classe on fait appel à une classe/méthode qui n’existe pas sur le système, l’application plante (cf. VerifyError). Par conséquent, notre classe ne doit être chargée (donc appelée) que si l’on a d’abord vérifié la version de l’API. Par exemple, imaginons que nous voulons faire appel à une méthode de la classe View qui n’existe que sous Jelly Bean et qui s’appelle « doSomeJellyBeanStuff() ».

Le code suivant ne marchera pas et fera crasher l’application si elle est exécutée sur une version antérieure à Jelly Bean :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    myView.doSomeJellyBeanStuff();
} else {
    myView.doSomeFallbackStuff();
}

Cela ne fonctionne pas car lorsque notre classe est chargée, la VM vérifie que la méthode View.doSomeJellyBeanStuff() existe, ce qui n’est vrai que sur Jelly Bean. Il faut donc passer par une classe intermédiaire, qui ne va être chargée que si la version est Jelly Bean ou ultérieure.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    new JellyBeanMethodWrapper().doStuff(myView);
} else {
    myView.doSomeFallbackStuff();
}

Il faut aussi créer la classe JellyBeanMethodWrapper :

public class JellyBeanMethodWrapper {
    public void doStuff(View myView) {
        myView.doSomeJellyBeanStuff();
    }
}

Si on ne veut pas créer trop classes, on peut aussi passer par des classes anonymes. Les Runnables sont très pratiques pour ça :

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    new Runnable() {
        public void run() {
            myView.doSomeJellyBeanStuff();
        }
    }.run();
} else {
    myView.doSomeFallbackStuff();
}

Ce dernier exemple fonctionne bien car la classe anonyme n’est chargée, donc vérifiée, que dans un contexte Jelly Bean.

Pour pouvoir faire cela, encore faut-il avoir connaissance de ce qui est disponible et ce qui ne l’est pas sur les différentes versions. La documentation de référence précise, pour chaque classe ou méthode, le numéro de version à partir de laquelle elle est disponible.

Il est aussi de filtrer la documentation par version d’API. Cela a notamment pour effet de griser les méthodes qui n’existent pas dans les versions inférieures.

Enfin, Eclipse est capable de détecter (grâce à l’outil Lint) l’utilisation d’une classe ou méthode qui n’existe pas sur la version d’API minimum déclarée dans le Manifest de l’application.

N’hésitez à commenter cet article si vous avez des questions !

Categories: Mobile Tags: , ,
  1. Pas encore de commentaire
  1. Pas encore de trackbacks


× neuf = 18