• Aucun résultat trouvé

Pour concevoir un gadget nous allons avoir besoin de réaliser plusieurs tâches : 1 créer un objet hérité de la classe AppWidgetProvider;

2 définir l’aspect visuel du gadget dans un autre fichier XML ; JARGON Widget, appwidget et gadget

Rappelons que le mot widget vient de la contraction des mots anglais window et gadget. À l’origine, il est utilisé pour désigner un programme miniature que l’on dispose sur son espace de travail. Tout au long de ce chapitre nous appellerons les AppWidgets des gadgets.

Figure 5–26 Exemples de gadgets (source Google)

Création d’interfaces utilisateur avancées

CHAPITRE 5 169

3 définir les paramètres du AppWidgetProvider dans un fichier XML ; 4 ajouter une activité pour personnaliser le gadget ;

5 déclarer le gadget dans le fichier de configuration de l’application.

Conception du fournisseur

La tâche la plus importante revient sans aucun doute à la conception de l’AppWidgetProvider, en d’autres termes au fournisseur de gadget. Attention son nom pourrait laisser sous-entendre que cette classe pourrait s’occuper de la création du gadget, or il n’en n’est rien. La classe AppWidgetProvider hérite directement du

BroadcastReceiver et n’est donc rien d’autre qu’un simple écouteur de messages.

Une fois ce constat réalisé, plusieurs possibilités s’offrent alors à vous : soit gérer ces messages à la manière d’un simple BroadcastReceiver en réécrivant la méthode

onReceive, soit en utilisant les méthodes simplifiées de l’AppWidgetProvider

(méthodes onUpdate et getSetting). Bien évidemment, nous ne pouvons que vous conseiller d’utiliser ces dernières.

Un gadget peut avoir plusieurs instances en cours d’utilisation : c’est pourquoi chaque gadget possède un identifiant propre. Le système garde également un comp-teur du nombre d’instances par type de gadget.

L’exécution du code ci-dessous s’effectue alors que le gadget est déjà créé (la création aura lieu avec une activité spécifique, détaillée plus loin dans ce chapitre), par consé-quent un identifiant lui est déjà attribué.

Dès qu’une modification s’opère sur un des gadgets de notre application, le système envoie un message à notre implémentation AppWidgetProvider pour l’en informer.

Code 5-43 : Conception du WidgetProvider

ATTENTION Les gadgets utilisent des contrôles RemoteViews

Sachez que les gadgets n’utilisent pas des contrôles standards : vous constaterez que les contrôles récu-pérés sont de type RemoteViews.

import android.app.PendingIntent;

import android.appwidget.AppWidgetManager;

import android.appwidget.AppWidgetProvider;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.net.Uri;

import android.preference.PreferenceManager;

import android.widget.RemoteViews;

Développer avec Android 170

Définir l’interface du gadget

Comme vous pouvez le voir dans le code précédent, nous utilisons les paramètres envoyés à la méthode onUpdate pour instancier un nouvel objet RemoteViews. Cette vue sera chargée depuis un fichier XML que nous aurons préalablement créé dans le dossier res/layout du projet. Ce fichier XML ressemble à n’importe quelle autre

public final class WidgetProvider extends AppWidgetProvider { @Override

public void onUpdate(Context context,

AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds);

// On récupère le texte dans les préférences

RemoteViews views = new RemoteViews(context.getPackageName() , R.layout.widgetlayout);

// Définit le texte

views.setTextViewText(android.R.id.text1, text);

// Crée un nouvel événement pour le clic

Intent intent = new Intent(context,WidgetConfigActivity.class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID ,appWidgetIds[i]);

intent.setData(Uri.parse("androidwidget://widget/id/"

+ appWidgetIds[i]));

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

// On ajoute cet événement sur la vue

views.setOnClickPendingIntent(android.R.id.text1, pendingIntent);

// On met à jour la widget

appWidgetManager.updateAppWidget(appWidgetIds[i], views);

} }

private String getSetting(Context context){

SharedPreferences settings =

PreferenceManager.getDefaultSharedPreferences(context);

return settings.getString("text",context.getString(R.string.hello));

} }

Création d’interfaces utilisateur avancées

CHAPITRE 5 171

déclaration d’interface à la différence que les composants utilisables, des RemoteViews, sont limités.

Voici les contrôles dont vous disposez :

FrameLayout

Nous utiliserons pour l’exemple suivant un simple bouton imbriqué dans un

LinearLayout comme défini ci-dessous.

Code 5-44 : Conception du widgetLayout.xml

Notez la taille du bouton en dip. Vous savez que chaque icône sur l’écran d’accueil du système Android tient une place bien précise. La formule de calcul de la taille d’une cellule est la suivante.

android:layout_width="283dip"

android:layout_height="54dip"

android:id="@android:id/text1"

android:textColor="#ff000000"

android:text="@string/hello"

android:background="@drawable/button"

android:gravity="center"

/>

</LinearLayout>

À RETENIR Taille minimale d’un gadget

Taille minimale d’un gadget en dip/dp = (Nombre de cellules * 74dip) – 2dip

Développer avec Android 172

Si vous utilisez le concepteur d’interface d’ADT (voir annexes), votre gadget devrait ressembler à celui ci-dessous.

Définir les paramètres du gadget

Vous devez stocker les paramètres du gadget (tailles minimales, fréquence de rafraî-chissement, etc.) dans un fichier XML à part du récepteur et de l’interface. C’est aussi dans ce fichier que vous attribuerez au gadget une activité pour le configurer pendant l’exécution (cf. plus loin dans ce chapitre).

Figure 5–27

Exemples de taille de gadget (source Google)

Figure 5–28 Exemple de gadget

Création d’interfaces utilisateur avancées

CHAPITRE 5 173

Créez ce fichier de paramétrage XML dans res/xml/widget.xml contenant la struc-ture suivante :

Code 5-45 : Conception du fichier widget.xml pour stocker les paramètres du gadget

Ainsi fait, notre gadget pourrait très bien fonctionner. Néanmoins il manque encore plu-sieurs choses. En effet, nous n’avons pas déclaré le gadget dans le fichier de configuration de l’application, ni d’activité pour créer ou configurer le gadget pendant l’exécution.

Associer le gadget à une activité

Nous allons effectuer d’une pierre deux coups et lancer une activité qui va à la fois créer le gadget et permettre sa configuration pendant l’exécution.

Pour ajouter un gadget, l’utilisateur doit appuyer sur l’écran d’accueil pour faire appa-raître un menu. Ce menu offre plusieurs possibilités dont l’ajout de gadget. Lorsque l’utilisateur choisit widget le système renvoie une liste d’applications ayant déclaré un gadget dans son fichier de configuration (nous le verrons en section suivante).

Lorsque l’utilisateur choisit un des éléments dans cette liste, le système va démarrer l’activité qui lui est associée et ainsi demander la création d’un gadget. Le système attendra la fermeture de cette activité pour obtenir l’autorisation de créer le gadget.

Ce mécanisme s’appuie sur l’emploi des méthodes startActivityForResult et

setResult que nous avons détaillées au chapitre 3.

Le système envoie également un extra de type AppWidgetManager.

INVALID_APPWIDGET_ID permettant d’identifier le gadget qui va être créé. Il ne nous reste plus qu’à charger et sauver les paramètres personnalisés liés à cet identifiant.

Code 5-46 : Conception de l’activité de configuration

<?xml version="1.0" encoding="utf-8"?>

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"

android:minWidth="294dip"

android:minHeight="72dip"

android:updatePeriodMillis="86400000"

android:initialLayout="@layout/widgetlayout"

android:configure="com.eyrolles.android.widget.WidgetConfigActivity" >

</appwidget-provider>

package com.eyrolles.android.widget;

import android.app.Activity;

import android.appwidget.AppWidgetManager;

import android.content.Intent;

import android.os.Bundle;

import android.preference.Preference;

Développer avec Android 174

Dans nos exemples nous avons sauvegardé/chargé une préférence dont voici le con-tenu, que vous placerez dans un fichier preferences.xml dans res/xml:

import android.preference.PreferenceActivity;

import android.preference.Preference.OnPreferenceChangeListener;

public class WidgetConfigActivity extends PreferenceActivity

implements OnPreferenceChangeListener { int mAppWidgetId;

@Override

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

// Nous ajoutons les contrôles via le fichier XML addPreferencesFromResource(R.xml.preferences);

findPreference("text").setOnPreferenceChangeListener(this);

// Nous récupérons l’identifiant du widget

mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);

// Nous testons la validité de l’identifiant

if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID){

// L’identifiant n’est pas valide on quitte

resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);

setResult(RESULT_OK, resultValue);

} }

@Override

public boolean onPreferenceChange(Preference preference, Object newValue) { // Mise à jour de la widget

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{mAppWidgetId});

sendBroadcast(intent);

return true;

} }

Création d’interfaces utilisateur avancées

CHAPITRE 5 175 Code 5-47 : Conception du fichier preferences.xml

Paramétrer le fichier de configuration de l’application

Une fois toutes ces étapes réalisées, vous devez encore déclarer l’existence du gadget dans le fichier de configuration de l’application en spécifiant :

le récepteur ;

l’activité de création et de configuration.

Pour déclarer le récepteur, ajoutez un élément <receiver> comme nœud de l’élé-ment<application>. La différence par rapport à un composant de type écouteur stan-dard est l’action du filtre et ses métadonnées. Le filtre doit capturer les actions de type

android.appwidget.action.APPWIDGET_UPDATE. Vous ajouterez des informations sup-plémentaires dans l’élément XML enfant <meta-data> pour spécifier le fichier de para-métrage du gadget (situé dans res/xml/widget.xml). La paire de cette métadonnée est composée du nom android.appwidget.provider et de sa valeur @xml/widget.

Pour déclarer l’activité de création et de configuration du gadget, insérez un compo-sant activité dans le fichier de configuration et déclarez un filtre sur l’action

android.appwidget.action.APPWIDGET_CONFIGURE:

Code 5-48 : Modification du fichier de configuration pour déclarer le gadget

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<EditTextPreference

android:summary="Cliquez pour modifier"

android:title="Titre"

android:key="text"

<application android:icon="@drawable/icon"

android:label="@string/app_name">

// L’activité de création et de configuration du gadget <activity android:name=".WidgetConfigActivity">

<intent-filter>

<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />

</intent-filter>

</activity>

Développer avec Android 176

Vous remarquerez qu’il n’y a pas d’activité par défaut dans ce fichier de configuration – pas de présence de filtre sur une action de type LAUNCHER – c’est pourquoi notre application ne démarrera pas si l’on clique sur son icône.

L’implémentation que nous venons de réaliser peut paraître simpliste et l’est dans la réalité. Néanmoins, elle regroupe toutes les fonctions de base d’un gadget et servira de modèle pour vos futures créations.

// La déclaration du récepteur du gadget <receiver android:name=".WidgetProvider">

<intent-filter>

<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

</intent-filter>

<meta-data

android:name="android.appwidget.provider"

android:resource="@xml/widget" />

</receiver>

</application>

<uses-sdk android:minSdkVersion="4" />

</manifest>

DUCÔTÉDELUTILISATEUR Ajouter un gadget sur le bureau

Pour activer un gadget, vous devez passer par le menu d’ajout des gadgets en laissant votre doigt appuyé sur une zone vierge de l’écran d’accueil. Le menu d’ajout apparaît alors. Choisissez Widgets puis sélectionnez le gadget que vous souhaitez ajouter à votre page d’accueil. Un écran de configuration s’ouvre alors afin de paramétrer le gadget et notamment son titre. Confirmez vos paramètres pour voir apparaître le gadget sur la page d’accueil de l’appareil.

Figure 5–29 Menu d’ajout du bureau Figure 5–30 Choix d’un widget

Création d’interfaces utilisateur avancées

CHAPITRE 5 177

En résumé

Vous pouvez désormais proposer des interfaces graphiques riches à vos utilisateurs, que ce soit en créant des composants personnalisés, en utilisant des adaptateurs, des animations ou en créant des menus. Vous conviendrez que la plate-forme Android est relativement bien fournie et aisée à appréhender. Sachez utiliser ces possibilités de façon harmonieuse, l’ergonomie de l’application étant un des aspects cruciaux dans le choix et l’adoption des applications par les utilisateurs.

Rendre accessible votre application à des millions de personnes ne parlant pas votre langue est aussi une excellente façon d’étendre son rayonnement et de diffuser vos applications au delà des frontières. Là aussi, la plate-forme Android apporte sa sim-plicité, et le complément ADT les outils nécessaires à votre productivité.

Si créer une application n’est pas suffisant pour vos utilisateurs et si vous souhaitez la mettre à disposition de l’utilisateur directement sur son bureau, la possibilité de créer des gadgets sera alors un excellent choix. Cependant, rien ne sert de créer un gadget mal réfléchi, ou juste parce que vous savez développer un gadget Android... Ne créez pas de gadgets qui soient trop... « gadget » !

Figure 5–31 Spécifier le titre du widget Figure 5–32 Résultat de l’ajout du widget sur le bureau

Quatre techniques sont à la disposition du développeur pour faire persister des don-nées dans le temps, chacune offrant un compromis entre facilité de mise en œuvre, rapidité et flexibilité, tout cela de façon unifiée quelle que soit l’application :

l’enregistrement du parcours de l’utilisateur dans l’application (écrans rencontrés avec leur contexte) ou persistance des activités (un écran étant lié à une activité).

Lorsqu’un utilisateur navigue dans une application, il est important de pouvoir conserver l’état de l’interface utilisateur pour préparer son retour sur les écrans potentiellement déchargés par le système pour gagner des ressources.

le mécanisme de préférence clé/valeur. Les fichiers de préférences sont avant tout utilisés pour stocker des préférences utilisateur, la configuration d’une application ou l’état de l’interface d’une activité. Ce mécanisme fournit un stockage simple et efficace par paire clé/valeur de valeurs primitives. Il existe également un système d’écran de préférences qui permet de créer des écrans de configuration rapide-ment et simplerapide-ment ;

l’utilisation d’un système de fichiers. Les fichiers sont le support de stockage élé-mentaire pour lire et écrire des données brutes dans le système de fichiers d’Android. Vous pourrez stocker des fichiers sur le support de stockage interne ou externe d’Android ;

6