Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Cross-plateforme : Android – Part 5 – Les ressources

[new:30/05/2013]De l’importance d’Android sur le marché aux raisons de s’y intéresser en passant par les bases de son fonctionnement, les 4 parties précédentes ont éclairé le chemin. Avant de passer à des réalisation concrètes, faisons un point sur une autre spécificité de l’OS, sa gestion des ressources.

Les ressources

Grâces aux ressources une application Android peut s’adapter aux différentes résolutions, aux différents form factors, aux différentes langues.

Devant le foisonnement des combinaisons de ces facteurs et puisque la gestion de l’UI n’est pas vectorielle, il faut de nombreuses ressources adaptées et forcément des conventions pour que l’OS puisse savoir comment choisir les bonnes.

Une application Android n’est que très rarement juste du code, elle s’accompagne ainsi de nombreuses ressources indispensables à son fonctionnement : images, vidéos, fichiers audio, sources xml, etc.

Tous ces fichiers sont des ressources qui sont packagées dans le fichier APK lors du processus de construction du logiciel (Build).

Quand on créée une application Android on retrouve toujours un répertoire spécial nommé “Resources”. Il contient des sous-répertoires dont les noms suivent des conventions précises pour séparer les ressources afin que l’OS puisse trouver celles qui sont nécessaires à un moment donné (changement d’orientation, langue, résolution, etc).

On retrouve au minimum les “drawable” (dessinables) que sont les images et vidéos, les “layout” que sont les Vues, les “values” qui servent aux traductions. D’autres sous-répertoires peuvent apparaitre selon le développement mais ceux-là sont ce qu’on appelle les ressources par défaut.

Les ressources spécialisées qu’on peut ajouter ensuite ont des noms formés en ajoutant au nom de base (“layout”, “drawable” …) une string assez courte appelée un qualificateur (qualifier). Par exemple les vues en mode portrait seront stockées dans “layout-port” et celles en paysage dans “layout-land”.

Il y a deux voies d’accès aux ressources sous Xamarin.Android : par code ou déclarativement en utilisant une syntaxe XML particulière.

Les noms de fichiers restent toujours les mêmes, c’est leur emplacement dans l’arbre des ressources qui indiquent leur catégorie. Cela oblige à une gestion fine et ordonnée de ces fichiers puisqu’on trouvera sous le même nom des vues en mode portait ou paysage comme des bitmap de différentes résolutions voire de contenu différent.

Les ressources de base

Dans un nouveau projet Xamarin.Android on trouve les fichiers suivants dans les ressources :

  • Icon.png, l’icône de l’application
  • Main.axml, la Vue principale
  • Strings.xml, pour faciliter la mise en place des traductions
  • Resource.designer.cs, un fichier auto-généré et maintenu par Xamarin et qui tient à jour la table de correspondance entre les noms en clair des ressources utilisés par le développeur et les ID numériques que Android sait gérer. Ce fichier joue le même rôle que “R.java” lorsqu’on utilise Eclipse/Java pour développer.
  • AboutResources.txt, fichier d’aide qui peut être supprimé. A lire pour s’y retrouver quand on débute.

 

Créer des ressources et y accéder

Créer des ressources est très faciles du point de vue programmation : il suffit d’ajouter des fichiers dans les bons répertoires… Créer réellement au sens de “produire” les ressources est un autre travail, généralement celui du designer (Vue, bitmap, vidéos) ou d’un musicien (musique ou sons en mp3). Cet aspect-là est essentiel mais ne nous intéresse pas ici.

Les fichiers doivent être marqués comme étant des ressources au niveau de l’application ce qui indique au builder comment les traiter, exactement comme sous WPF, Silverlight, WinRT, etc.

On notera qu’à la base Android ne supporte que des noms en minuscules pour les ressources. Toutefois Xamarin.Android est plus permissif et autorise l’utilisation de casses mixtes. Mais il semble plus intelligent de prendre tout de suite les bons réflexes et de n’utiliser que des noms formés selon la convention de l’OS, c’est à dire en minuscules.

Accéder aux ressources par programmation

Les ressources sont des fichiers marqués comme tels et rangés dans des répertoires particuliers de l’application. Un système automatique maintient une équivalence entre les noms des ressources et leur véritable ID numérique géré par Android. C’est le rôle de “Resources.designer.cs” qui définit une classe “Resource” ne contenant pas de code mais une série de déclaration de type “nomRessource = xxx” où “xxx” est l’ID entier.

Un exemple de ce fichier :

public partial class Resource
{
    public partial class Attribute
    {
    }
    public partial class Drawable {
        public const int Icon=0x7f020000;
    }
    public partial class Id
    {
        public const int Textview=0x7f050000;
    }
    public partial class Layout
    {
        public const int Main=0x7f030000;
    }
    public partial class String
    {
        public const int App_Name=0x7f040001;
        public const int Hello=0x7f040000;
    }
}

 

On voit que chaque ressources est déclarée à l’intérieur d’une classe imbriquée, créant ainsi une hiérarchie facilitant l’accès aux ressources d’un type ou d’une autre.

Tel que se présente le fichier exemple plus haut, l’icône de l’application “Icon.pgn” pourra être référencée dans le code en utilisant “Resource.Drawable.Icon”

La syntaxe complète étant :

@[<PackageName>.]Resource.<ResourceType>.<ResourceName>

 

La référence au package est optionnelle mais peut être utile lorsqu’une application complexe est constituée de plusieurs APK.

Accéder aux ressources depuis un fichier XML

A l’intérieur d’un fichier XML, généralement – mais pas seulement – une Vue, il est possible d’accéder aux ressource par une syntaxe particulière, une sorte de “binding statique” :

@[<PackageName>:]<ResourceType>/<ResourceName>

 

L’AXML suivant montre cette syntaxe :

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
        android:orientation="vertical" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent">
    <ImageView android:id="@+id/myImage" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:src="@drawable/flag" />
</LinearLayout>

 

Le conteneur de type “LinearLayout” est utilisé comme base pour contenir un “ImageView”, un contrôle affichant une image. La source (propriété “android:src”) est fixée en utilisant la syntaxe “@” suivi du répertoire type de ressource (“drawable”) et du nom de la ressource “flag” séparé par un slash.

Les différentes ressources

Nous avons vu les types de ressources les plus communs comme les images (drawable), les vues (layout) ou les valeurs (values), Android définit bien d’autre types qui seront utilisés de la même façon (définition d’un sous-répertoire).

  • animator. Fichiers XML définissant des animations de valeurs. Cela a été introduit dans l’API de niveau 11 (Android 3.0).
  • anim. Fichiers XML définissant des animations spéciales destinées aux Vues par exemple en cas de rotation, de changement de vue, etc.
  • color. Fichiers XML définissant des listes d’états de couleurs. Par exemple un bouton peut avoir des couleurs différentes selon son état (appuyé, désactivé…), ces changements de couleur en fonction de l’état de l’objet sont stockés dans une liste d’états de couleurs.
  • drawable. Toutes les ressources “dessinables”, donc les graphiques au sens large (gif, png, jpeg, formes génériques définies en XML, mais aussi les “nine-patches” que nous verrons ultérieurement).
  • layout. Tous les fichiers AXML définissant les vues.
  • menu. Fichiers XML définissant les menus d’une application comme le menu des options, les menus contextuels et les sous-menus.
  • raw. Tout fichier dans son format natif binaire. Ces fichiers ne sont pas traités par Android mais peuvent être utilisés par l’application.
  • values. Fichiers XML définissant des couples clé/valeur généralement utilisés pour définir des messages affichés par l’application.
  • xml. Fichiers XML quelconque pouvant être lus par l’application pour son fonctionnement (dans le même esprit que les fichiers de configuration de .NET).

 

Comme on le voit, Android se base beaucoup sur des conventions de nommage et des arborescences de fichiers. Cela est rudimentaire, ne coute pas très cher à gérer pour l’OS tout en offrant un niveau de souplesse suffisant au développeur.

Toutefois qui dit conventions nombreuses et rigides implique une bonne connaissance de celles-ci et une bonne organisation du travail pour ne pas commettre d’erreurs !

La notion de ressources alternatives

Le sujet a été évoqué à plusieurs reprises ici : le répertoire “Resources” se structure en sous-répertoires tels que ceux listés ci-dessus mais chaque sous-répertoire peut se trouver décliner à son tour en plusieurs branches qui vont permettre de différencier les ressources adaptées à une situation ou une autre.

Les principales décisions concernent les locales (localisation de l’application), la densité de l’écran, la taille de l’écran, l’orientation de l’unité mobile.

Les qualificateurs sont alors utilisés en prenant le nom du répertoire de base et en y ajoutant un slash suivi d’un code spécifique.

Pour les ressources de type “values” par exemple, si je souhaite créer une localisation en allemand, je placerais le fichier de ressource dans “Resources/values-de”. Ici c’est le code pays qui est utilisé comme qualificateur.

Il est possible de créer des combinaisons, pour cela chaque qualificateur ajouté est simplement séparé du précédent par une tiret. Toutefois l’ordre d’apparition des qualificateurs doit respecter celui de la table suivante, Android n’analyse pas toutes les substitutions possibles et se fie uniquement à un ordre établi (toujours le principes de conventions rigides permettant de simplifie à l’extrême les traitements côté OS).

  • MCC et MNC. Ce sont les Mobile Country Code et les Mobile Network Code. Les premiers indiquent le code pays et servent notamment pour les drapeaux ou autres mais pas la localisation, les seconds permettent dans un pays donné de différencier les réseaux. On peut supposer une application qui affiche un texte différent par exemple si le réseau est celui de Free ou de Orange.
  • Langage. Code sur deux lettres suivant ISO 639-1 optionnellement suivi par un code de deux lettres de la région suivant ISO-3166-alpha-2. Par exemple “fr” pour la france, “fr-rCA” pour nos amis de l’autre côté de la “grande mare” (les canadiens francophones donc). On note la différence de casse ainsi que la présence de “r” pour la région.
  • taille minimum. Introduit dans l’API 13 (Android 3.2) cela permet de spécifier la taille minimale de l’écran autorisé pour la ressource décrite. Pour limité à une taille de 320 dp le qualificateur prendra la forme “sw320dp”. Nous reviendrons sur les “dp” qui définissent mieux que les pixels les tailles exprimées sous Android.
  • Largeur disponible. Même principe mais la largeur ici peut dépendre du contexte notamment de la rotation (alors que les caractéristiques écran restent les mêmes, la machine ne se changeant pas toute seule…). La forme es t “w<N>dp”. Pour limiter une ressource à une largeur écran effective de 720 dp on ajoutera le qualificateur “w720dp”. Cela a été introduit dans Android 3.2 (API 13).
  • Hauteur disponible. Même principe pour la hauteur disponible de l’écran. La lettre “h” prend la place de la lettre “w”.
  • Taille écran. Généralisation des tailles écran présente depuis Android 2.3 (API 9). Plus générique et moins fin que les qualificateurs évoqués ci-dessus mais actuellement permettant de couvrir 99% des machines en circulation (environ 30 à 40% d’Android 2.3). Les tailles sont ici des noms fixes “small, normal, large” et “xlarge”.
  • Ratio. Permet un filtrage des ressources en fonction du ratio de l’écran plutôt que sur sa taille. Cela est couvert par l’API niveau 4 (Android 1.6) et prend les valeurs “long” et “notlong”.
  • Orientation. Beaucoup plus utilisés, les qualificateurs “land” (landscape, paysage) et “port” (portrait) permettent de définir des ressources, telles que les Vues ou des drawables en fonction de l’orientation de la machine.
  • Dock. Permet de savoir si la machine est placée dans son dock (de bureau ou de voiture) pour celles qui savent le détecter. Les valeurs possibles sont “car” ou “desk”.
  • Nuit. Pour faire la différence en la nuit et le jour ce qui permet d’afficher des couleurs différentes (du rouge en mode nuit pour une carte des étoiles par exemple, couleur n’aveuglant pas), des images différentes, etc. Les valeurs possibles sont “night” et … non pas ‘day’ mais “nonight” !
  • Dpi. Filtre sur la résolution de l’écran en DPI. Cela est important pour les drawables car une bitmap créée avec un certain nombre de pixels pourra devenir toute petite sur une écran de type rétina ou énorme sur un écran de mauvaise résolution. Il est donc préférable d’avoir préparé plusieurs variantes selon les DPI. La valeur s’exprime en code : “ldpi" pour Low densité (basse densité), “mdpi” pour densité moyenne, “hdpi” pour haute densité, “xhdpi” pour extra haute densité, “nodpi” pour les ressources qui ne doivent pas être retaillées, “tvdpi” introduit en API 13 (Android 3.2) pour les écran entre le mdpi et le hdpi.
  • Type touch. Pour filtrer en fonction du type d’écran tactile : “notouch” pas de tactile, “stylus” pour un stylet, et “finger” pour le tactile classique avec les doigts.
  • Clavier. Filtrage selon le type de clavier disponible (ce qui peut changer durant le cycle de vie de l’application). “keyseposed” s’il y a un clavier physique ouvert, “keshidden” il n’y a pas de clavier physique et le clavier virtuel n’est pas ouvert, “keyssoft” s’il y a un clavier virtuel qui est activé.
  • Mode de saisie. Pour filtrer selon le mode de saisie principal. “nokeys” s’il n’y a pas de touches hardware, “qwerty” s’il y a un clavier qwerty disponible, “12key” quand il y a un clavier 12 touches physiques présent.
  • Navigation. Disponibilité de touches de navigation (5-directions ou type d-pad). “navexposed” si le système existe, “navhidden” s’il n’est pas disponible.
  • Navigation primaire. Type de navigation offerte “nonav” aucune touche spéciale en dehors de l’écran tactile lui-même, “dpad” '(d-pad, pad directionnel) disponible, “trackball”, “wheel”.
  • Plateforme. Enfin, il est possible de filtrer les ressources sur la version de la plateforme elle-même en spécifiant le niveau de l’API : “v11” pour l’API de niveau 11 par exemple (Android 3.0).

 

Si cette énumération peut sembler fastidieuse, elle permet de bien comprendre les problèmes qui se pose au développeur et au designer …

La liberté sous Android est telle, le foisonnement des modèles, des résolutions, etc, est tel qu’il peut s’avérer presque impossible d’écrire une application s’adaptant à toutes les possibilités. Si toutes les ressources doivent être créées pour toutes les combinaisons possibles, il faudra plus d’espace de stockage pour l’exécutable que n’en propose la plupart des unités mobiles !

Il faudra forcément faire des choix et savoir jongler avec des mises en page souples s’adaptant à toutes les situations, au moins aux plus courantes…

Le problème est moindre si on vise un type particulier de machines (cibler que les tablettes par exemple), une ou deux langues précises, etc.

Le problème n’est pas typique d’Android, il se pose à tous les développeurs sous Windows aussi.

Il n’y a guère que chez Apple où tout cela n’a pas de sens, puisque l’acheteur n’a pas de choix…

Android utilise un mécanisme déterministe et connu pour choisir dans les ressources. Ainsi il va éliminer tout ce qui est conflit avec la configuration de la machine en premier. Il éliminera ensuite toutes les variantes qui ont des qualificateurs s’éloignant de la configuration en prenant l’ordre de la liste ci-dessus comme guide.

Pour s’aider à prendre les bonnes décisions, Google fournit aussi des outils analytiques en ligne comme les Dashboards qui permet de connaitre au jour le jour la répartition des versions d’Android dans le monde, celui des API etc.

Par exemple, à la présente date la répartition est la suivante :

image

Pour les tailles écran nous obtenons le tableau suivant :

image

Ces informations sans cesse mises à jour sont très importantes pour le développeur et le designer puisqu’elles permettront de faire des choix raisonnables en termes de niveau d’API supporté et taille/résolution d’écran.

Créer des ressources pour les différents types d’écran

Je viens d’en parler avec les Dashboards Google, le chalenge le plus important peut-être pour le développeur et le designer est de s’adapter au foisonnement des formats disponibles (taille et résolution d’écran).

Si la majorité des utilisateurs ont un écran de taille “normale”, certains ont des écrans petits (small), grands (Large) voire super grands (Xlarge). Et cela ne concerne que la taille écran, pour une même taille physique d’écran il existe de nombreuses résolutions, de “ldpi”, basse densité, à xxhdpi, la super haute densité de type rétina.

Normal ?

Qu’est que la “normalité” ? Non, ne fuyez pas, nous n’allons pas faire un devoir de philo ! Sourire

Mais on peut se demander comment est défini la “normalité” dans les tailles d’écran. C’est un concept flou et qui n’apprend pas grand chose. C’est bien entendu sans compter sur la documentation Google qui précise ce genre de choses :

image

 

Un écran  “normal” est un écran qui fait grosso-modo entre 3 et 4.5 pouces. Un pouce faisant 2.56 cm. A partir de là tout le reste se décline. Les “small” (petits) sont en dessous de 3”, les grands au-dessus de 4,5” jusqu’à près de 7 pouces, disons le format “phablet” ou mini tablette, le “xlarge” commence à 7” et s’étant jusqu’au-delà de 10 pouces. Si on vise un développement smartphone il est clair qu’aujourd’hui il faut viser le support de “normal” et “large”, si on vise les tablettes et les phablettes il faut cibler “large” et “xlarge”. Cela limite les combinaisons malgré tout.

 

Les résolutions comptent beaucoup, et sont elles aussi définies par la documentation :

image

Le “hdpi” et le “'xhdpi” sont les plus utilisées à ce jour, c’est à dire que les résolutions les plus faibles en dessous de 200 DPI peuvent de plus en plus être ignorées.

Sous Android les tailles des objets peuvent ainsi varier grandement selon le support, une image de 100x100 pixels n’aura pas le même rendu et la même taille sur un écran très haute densité que sur un écran de 100 DPI. Cette variabilité a obligé à définir un autre système de mesure, indépendant de ces paramètres, les “DP”.

Les “Density-independent pixel”

Les “DP” sont une unité de mesure virtuelle remplaçant la notion de pixel trop variable dans des environnements où la résolution des écrans est d’une grande disparité.

Cela permet notamment de fixer des règles de mise en page indépendantes de la résolution.

La relation entre pixel, densité et “dp” est la suivante :

px = dp * dpi/160

Exemple : sur un écran de 300 DPI de densité, un objet de 48 dp aura une taille de (48*300/160) soit 90 pixels.

Les tailles écran en “dp”

Les tailles écran que nous avons vu plus haut peuvent s’exprimer en “dp” plutôt qu’en pouces ce qui facilite la création de patrons pour sketcher les applications puisque toutes les tailles s’expriment en “dp” sous Android.

  • xlarge définit ainsi des écrans qui font au minimum 960x720 dp
  • large, 640x480 dp
  • normal, 470x320 dp
  • small, 426x320 dp

 

Avant Android 3.0 ces tailles n’étaient pas aussi clairement définies, le marché était encore flou et les avancées techniques très rapides. De fait on peut trouver de veilles unités datant d’avant Android 3.0 qui, éventuellement, pourrait rapporter une taille qui ne correspondrait pas exactement à celles indiquées ici. Cette situation est malgré tout de plus en plus rare et peut être ignorée.

Supporter les différentes tailles et densités

Le foisonnement des matériels très différents complique un peu la tâche du développeur et du designer, mais comme nous l’avons vu, dans la réalité, la majorité du marché se trouve être couvert par deux ou trois combinaisons principales, ce qui simplifie les choses.

De plus Android fait lui-même le gros du travail pour adapter un affichage à un écran donné. Il n’en reste pas moins nécessaire de lui donner un “petit coup de main” de temps en temps pour s’assurer du rendu final de ses applications.

La première des choses consiste à adopter les “dp” au lieu des “pixels”. Rien que cela va permettre une adaptation plus facile des mises en page et des images. Android effectuera une mise à l’échelle de ses dernières au runtime. Mais comme vous le savez, le problème des bitmaps c’est qu’elle ne supportent pas de grandes variations de taille même avec de bons algorithmes…

Les mises à l’échelle des bitmaps ne tiennent que dans une fourchette assez faible de pourcentages, au-delà d’une certaine valeur de zoom (avant ou arrière), l’image apparaitra floutée ou pixellisée.

Pour éviter ce phénomène les environnements vectoriels comme XAML apportent une solution radicale, tout est toujours affiché à la bonne résolution. Mais sous Android qui n’est pas vectoriel il faudra fournir des ressources alternatives en se débrouillant pour couvrir les principales cibles.

Limiter l’application à des tailles écran

Lorsqu’on a fait le tour des tailles écran que l’application peut supporter il peut s’avérer assez sage de le préciser dans les paramètres (le manifeste de l’application, jouant le même rôle que sous WinRT) afin de limiter le téléchargement de l’application.

C’est à chaque développeur de trancher, mais d’une façon générale je conseille plutôt d’interdire le téléchargement aux tailles non gérées proprement par l’appareil plutôt que de laisser un potentiel utilisateur charger une application qui n’est pas supportée et qui donnera l’impression d’être de mauvaise qualité. Cette frustration là créée une impression négative difficile à effacer, la frustration ne pas pouvoir télécharger n’est pas du même ordre et peut même créer l’envie…

C’est ainsi dans le fichier AndroidManifest.XML qu’on peut jouer sur la section “supports-screens” pour déclarer les tailles supportées par l’application.

La conséquence est que l’application n’apparaitra dans Google Play si ce dernier est accédé depuis une machine non supportée. Si l’installation est faite “de force” par d’autres moyens, elle tournera bien entendu sans encombre, sauf que sa mise en page sera certainement peu agréable. Le manifeste joue donc un rôle de filtrage ici pour le store, mais pas pour le runtime.

Voici un exemple de déclaration vu depuis Xamarin Studio (on peut voir les mêmes données sous VS) :

image

Fournir des mises en page alternatives

Android tentera toujours d’afficher les vues qui sont chargées par une application en leur appliquant si besoin un redimensionnement. Cela peut suffire dans certains cas, dans d’autres il peut être plus judicieux d’adapter cette mise en page en réduisant ou éliminant certains éléments (pour les petites tailles) ou en agrandissant ou ajoutant certaines zones (pour les grandes tailles).

Depuis l’API 13 (Android 3.2) l’utilisation des tailles écran est deprecated, il est conseillé d’utiliser la notation “sw<N>dp”. Si vous visez une compatibilité maximale en ce moment, vous choisirez de supporter Android 2.3 au minimum, soit l’API de niveau 10. Dans un tel cas vous utiliserez le système de tailles écran vu plus haut. Si vous décidez de cibler 3.2 et au-delà il faut alors utiliser la nouvelle notation.

La décision est un peu difficile à l’heure actuelle car la version 2.3 est un peu un pivot, 50 % de machines font tourner cette version (et les inférieures) et 50% font tourner 3.2 et au-delà. On comprend que beaucoup de développeurs préfèrent encore aujourd’hui, sauf nécessité (nouvelles API), supporter 2.3.

Dans l’arborescence des ressources, pour supporter un écran de 700dp de large minimum (simple exemple) il faudra fournir une vue alternative de cette façon :

image

On remarque la section “layout” par défaut avec le “main.axml” et la section “layout-sw700dp” avec un fichier “main” lui aussi renommé en fonction de ce filtrage.

On se rappellera qu’un téléphone typique aujourd’hui est dans les 320 dp de large, qu’une phablette de type Samsung Note en 5” fait 480 dp de large, qu’une tablette 7” est dans 600 dp de large alors qu’un tablette 10” compte 720 dp minimum de large.

Si l’application cible les version sous la 3.2 (donc les API jusqu’au niveau 12), les mises en page seront précisées en utilisant la codification “normal”, “large”, etc :

image

Si les deux procédés sont mis en place simultanément, ce qui est tout à fait possible, c’est la nouvelle notation qui prend la précédence à partir de l’API 13. Si une application veut cibler les machines avant 3.2 en même temps que celles à partir de 3.2 et qu’elle souhaite gérer plusieurs tailles d’écran elle pourra le faire en mixant les deux notations donc.

Fournir des bitmaps pour les différentes densités

Comme je l’ai déjà expliqué, Android fait une mise à l’échelle des bitmap en fonction de la résolution. Cela peut suffire mais quand l’écart est trop grand les bitmaps peuvent être floutés ou pixellisés. Dans ce cas il convient de fournir des versions adaptées aux différentes résolutions.

Le principe a déjà été exposé et ne présente pas de difficultés. Mais au lieu de tout faire à la main on peut aussi utiliser des outils existants…

Créer les ressources pour les densités différentes

La création des images dans les différentes résolutions est une tâche un peu ennuyeuse surtout quand on fait des adaptations de ces images en cours de développement, ce qui réclame de générer à nouveau toute la série de résolutions.

Google met à la disposition des développeurs un outil assez simple mais très pratique pour faciliter cette tâche : l’Android Asset Studio. Cet outil en ligne regroupe plusieurs utilitaires permettant de générer des icones pour la barre de lancement, ou pour la barre d’action, pour les notifications, etc. Le tout en respectant les tailles standard en générant toutes les séries nécessaires au support des différentes résolutions.

Il est possible de partir d’une image qu’on fourni, d’un symbole sélectionné dans une librairie ou d’un texte :

image

Une fois les réglages effectués l’outil génère la série d’images et permet de télécharger un paquet zippé.

D’autres outils communautaires existent dans le même genre.

Automatiser les tests

Tant de combinaisons possibles de tailles écran et de résolutions créent une situation un peu désespérante à première vue… “Comment vais-je pouvoir tout tester ?”

Comme je l’ai déjà indiqué, le principe est surtout de savoir se limiter et ne pas chercher à couvrir 100% du parc mondial…  Ensuite il faut disposer de machines réelles pour tester. Les émulateurs ont toujours leurs limites.

Lorsqu’une application est vraiment importante (mais y en a t il qui ne le sont pas ?) on peut aussi utiliser des services spécialisés. ApKudo permet de certifier une application comme sur le store Apple ou Microsoft par exemple, avec un retour d’information sur tous les problèmes rencontrés, The Beta Family fonctionne sur le principe développeurs/testeurs, vous avez des retours de testeurs, en échange vous leur donner une licence ou autre chose, ou bien Perfecto Mobile, eux possèdent presque toutes les machines et lancent un test en parallèle sur près de 300 unités différentes, vous obtenez des résultats clairs et vous savez exactement où ça passe et où ça ne passe pas.

Ces services permettent d’avoir une bonne idée de la fiabilité de l’installation, de l’UI, etc, et ce gratuitement ou presque.

Localisation des strings

Parmi les ressources essentielles d’une application se trouvent les chaines de caractères. Une approche particulière est nécessaire dès lors que ces chaines doivent être traduites.

Il n’est alors plus question de les stocker en dur dans l’interface ou dans le code… Et comme on ne sait jamais, je conseille toujours de faire “comme si” la traduction était nécessaire dès le départ. Dans les projets directement multi-lingue la question ne se pose bien entendu pas.

Le procédé est très simple puisque dans le répertoire des ressources d’une application se trouve le sous-répertoire “values”. C’est ici que se trouve par défaut “strings.xml”, un  fichier de définition de chaines.

En spécialisation le répertoire “values” en fonction du code pays (et du code région si vraiment cela est nécessaire) on pourra copier le fichier “strings.xml” et le traduire dans les différentes langes supportées, Android chargera les bonnes données automatiquement.

Par exemple une application supportant une lange par défaut ainsi que l’espagnol et l’allemand présentera une arborescence de ce type :

image

Une vue accédant aux données localisées présentera un code de ce type :

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<Button  
   android:id="@+id/myButton"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
android:text="@string/hello"
   />
</LinearLayout>

 

Le bouton défini en fin de fichier utilise un texte puisé dans la ressource “string” qui porte le nom de “hello”. La correspondance entre ce nom, “hello” et sa valeur est effectuée dans le fichier “strings.xml” correspondant à la langue en cours, choix effectué par Android automatiquement.

Ce mécanisme, comme le reste sous Android, est basé sur des principes simples, un peu frustres (comme des conventions de noms de répertoires) mais cela permet d’assurer des fonctions très sophistiquées sans consommer beaucoup de ressources machine. Quand on compare avec les mécanismes de localisation sous Silverlight, WPF ou WinRT on s’aperçoit que MS ne choisi par toujours le chemin le plus court pour arriver au résultat. L’astuce de Google c’est d’avoir une vision très pragmatique des besoins et d’y avoir répondu de façon très simple. Pas de quoi passer une thèse donc sur la localisation sous Android, mais à la différence d’autres OS c’est justement très simple, robuste, et peu gourmand. Android vs Windows Phone c’est un peu l’approche russe vs celle de la Nasa… Les trucs de la Nasa sont toujours d’un niveau technique incroyable, mais quand on compare, finalement, aujourd’hui ce sont les russes qui seuls peuvent ravitailler l’ISS … La simplicité et la rusticité ont souvent du bon, même dans le hi-Tech !

Conclusion

Les ressources sont essentielles au bon fonctionnement d’une application car elle n’est pas faite que de code mais aussi de vues, d’images, d’objets multimédia.

Android offre une gestion particulière des ressources car les types d’unités faisant tourner cet OS sont d’une variété incroyable et qu’il fallait inventer des mécanismes simples consommant très peu.

Avec un bon ciblage et une bonne organisation du développement et du design il est tout à fait possible de créer des applications fonctionnant sur la majeure partie du parc actuel.

Il ne reste plus qu’à mettre tout ceci dans le chaudron à idées et à commencer le développement de vos applications cross-plateformes sous Android !

Il reste bien deux ou trois choses à voir encore, mais nous le ferons en partant d’exemples…

Stay Tuned !

blog comments powered by Disqus