La dernière version de l'OS pour appareils mobiles Android, FroYo (Android 2.2) a été annoncée lors du Google I/O le 20 mai dernier.
Cette nouvelle version compte de nombreuses nouveautés. Notamment le support de flash, la possibilité de transformer un téléphone en hotspot wifi. Et une autre fonctionnalité, Android Cloud Device Messaging. C2DM permet à une application web de transmettre des données à une application installée sur un appareil Android.
Ainsi, si votre application est un lecteur de flux RSS par exemple, votre serveur pourra transmettre de manière asynchrone à un appareil qui utilise celle-ci que de nouveaux éléments sont à lire. Alors, l'application n'aura plus qu'à aller automatiquement rafraichir la liste des entrées.
Voici en bref comment fonctionne C2DM :
- Lorsque vous installez l'application sur un appareil Android, celle-ci s'enregistre auprès de Google, obtient un identifiant d'enregistrement et transmet cet identifiant à votre serveur en ligne.
- Lorsque le serveur a besoin de pousser un message à l'appareil, il fait une requête POST chez Google.
- Google transmet ce message à l'appareil, qui exécute alors l'évènement approprié.
A n'importe quel moment, l'application peut se désinscrire de C2DM afin d'arrêter de recevoir les notifications de push.
En conséquent cet article est plus théorique que autre chose car je n'ai pas pu tester son utilisation sur une réelle application.
Enregistrement d'une application à C2DM
Afin de pouvoir recevoir des notifications, votre application doit s'enregistrer dans C2DM. Pour cela, vous devez tout d'abord avoir les permissions appropriées configurées dans votre fichier AndroidManifest.xml. Voici un exemple de contenu pour ce document permettant à votre application de recevoir des push :
<manifest package="com.example.myapp" ...>
<!-- Seule cette application peut recevoir les messages et le résultat de l'enregistrement à C2DM -->
<permission android:name="com.example.myapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.example.myapp.permission.C2D_MESSAGE" />
<!-- Cette application a l'autorisation de recevoir des messages -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Il est nécessaire d'avoir l'autorisation d'accéder à Internet pour pouvoir recevoir les messages. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Seuls les serveurs C2DM peuvent transmettre des messages à l'application. -->
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<!-- L'application peut recevoir des messages -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.myapp" />
</intent-filter>
<!-- L'application peut recevoir l'identifiant d'enregistrement au serveur C2DM -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.example.myapp" />
</intent-filter>
</receiver>
Notre application est maintenant autorisée à s'enregistrer à C2DM. Mais cela n'est pas encore fait. Pour cela nous allons transmettre un Intent permettant d'identifier notre application.
Intent regIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
regIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0);
regIntent.putExtra("sender", "you@example.com");
startService(regIntent);
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) {
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
// L'enregistrement a échoué. Réessayez plus tard.
} else if (registration != null) {
// L'enregistrement a correctement été effectué.
// Transmettez ici l'identifiant d'enregistrement au serveur Web qui transmettra les messages.
}
}
}
Nous commençons ici par initialiser un Intent de type C2DM.intent.REGISTER. Puis nous transmettons deux valeurs à celui-ci :
- Une identification de notre application, permettant de restreindre l'envoi de messages de push uniquement au serveur autorisé à cela.
Un email, identifiant du compte autorisé à transmettre des messages de push à l'application. C'est généralement un email défini par le développeur de l'application.
startService(regIntent);
Puis nous initialisons le service. Ensuite nous écoutons la réception de tout message. Si il s'agit d'un message C2DM indiquant que nous avons réussi à nous enregistrer, nous validons cet enregistrement.
String registration = regIntent.getStringExtra("registration_id");
Nous récupérons l'identifiant d'enregistrement transmis à l'application.
if (regIntent.getStringExtra("error") != null) {
// L'enregistrement a échoué. Réessayez plus tard.
} else if (registration != null) {
// L'enregistrement a correctement été effectué.
// Transmettez ici l'identifiant d'enregistrement au serveur Web qui transmettra les messages.
}
Enfin nous vérifions que l'enregistrement a été correctement été effectué et que l'identifiant a été correctement créé. Si c'est bien le cas, il ne vous restera plus qu'à transmettre cet identifiant à votre serveur web qui pourra alors commencer à envoyer des messages de push.
Les messages de push pourront maintenant être transmis à notre application. Voyons comment les recevoir et les traiter.
Transmission d'un message à l'application
Pour pouvoir transmettre des messages de push, il faut que votre serveur soit capable de transmettre des données en POST à Google. La requête doit être faite à l'URL https://android.apis.google.com/c2dm/send
Plusieurs paramètres sont requis pour transmettre un message à l'application :
- registration_id - Il s'agit de l'identifiant d'enregistrement transmis à l'application lorsque celle-ci a activé C2DM.
- collapse_key - Un identifiant permettant de regrouper divers messages similaires. Ainsi, si l'appareil est hors ligne lorsque vous envoyez ce message, il ne sera transmis que plus tard. Tous les messages ayant la même collapse_key seront transmis en un seul lors de la reconnexion de l'appareil, évitant ainsi trop de messages similaires en simultané.
- data.
- Une liste de clés/valeurs qui seront transmises à l'application. Vous pouvez en transmettre autant que vous le désirez. - delay_with_idle - Si l'appareil est en veille lorsque le message est envoyé, il ne sera alors pas reçu tout de suite mais uniquement lorsque l'utilisateur réactivera la machine.
- Authorization: GoogleLogin auth=[AUTH_TOKEN] - Votre clé d'identification GoogleLogin.
La clé d'identification est transmise au serveur lorsque vous utilisez ClientLogin for Installed Applications. Elle permet de vous identifier. Vous devez être identifié avec l'email transmis et autorisé lorsque l'appareil s'est enregistré auprès de C2DM.
Google répondra alors à cette requête avec trois codes HTTP possibles :
- 200 - Aucune erreur technique ne s'est produite. Cela ne signifie cependant pas que votre message a été envoyé.
Le contenu de la page renvoyée peut contenir les choses suivantes :
- id=<ID> - Identifiant du message si celui-ci a correctement été transmis.
- Error=<code d'erreur> - Code d'erreur si le message n'a pas pu être transmis.
- QuotaExceeded - Trop de messages ont été transmis. Réessayez plus tard.
- DeviceQuotaExceeded - Trop de messages ont été transmis sur un appareil en particulier. Réessayez plus tard.
- InvalidRegistration - identifiant d'enregistrement manquant ou invalide. Vous devez arrêter d'envoyer des messages à cet appareil.
- NotRegistred - L'enregistrement n'est plus valide. Vous devez arrêter d'envoyer des messages à cet appareil.
- MessageTooBig - Le message est trop gros. Réduisez le.
- MissingCollapseKey - la collapse_key est manquante et doit être include.
- 503 - Indique que le serveur est actuellement indisponible. Un entête Retry-After est alors transmis. Votre application ne doit pas retransmettre de requête avant la date transmise.
- 401 - Indique que votre clé ClientLogin n'est pas valide.
Réception d'un message depuis l'application
Une fois que votre serveur a correctement transmis un message à Google, celui-ci retransmettra ce même message à votre appareil Android. A vous alors de l'intercepter. Pour cela, de la même manière que lorsque tout à l'heure, nous écoutions la réception de la validation de l'enregistrement de l'appareil, nous allons écouter la réception d'un nouveau message.
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
String accountName = intent.getExtras().getString(Config.C2DM_ACCOUNT_EXTRA);
String message = intent.getExtras().getString(Config.C2DM_MESSAGE_EXTRA);
Log.d("PUSH", "Requête de push transmise pour le compte " + accountName);
}
}
Nous écoutons donc la réception d'un nouveau message.
if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
Et nous vérifions qu'il s'agit bien de la réception d'un message de push.
String accountName = intent.getExtras().getString(Config.C2DM_ACCOUNT_EXTRA);
Ici, nous récupérons le nom du compte Google depuis lequel le message de push a été transmis. Toutes les clés/valeurs que vous aurez transmis dans la requête POST seront transmis et accessibles ici.
Log.d("PUSH", "Requête de push transmise pour le compte " + accountName);
Enfin ici, nous ne faisons que loguer la réception d'un nouveau message de push. A vous de faire ce que vou désirez.
Désinscription d'une application de C2DM
A tout moment, vous devez permettre aux utilisateurs de vos applications d'arrêter de recevoir des messages de push. Pour cela, il vous suffit de définir un Intent com.google.android.c2dm.intent.UNREGISTER, qui transmettra alors à Google votre demande de désinscription du push pour cette application.
Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
startService(unregIntent);
Vous pouvez aisément constater que nous définissons notre intent de la même manière que nous avons défini celui nous permettant de nous enregistrer au push, seul le nom de celui-ci change.
Conclusion
Avec C2DM, Google nous propose (enfin) une fonctionnalité permettant de transmettre des notifications diverses aux applications installées sur un appareil de manière intantanée (ou presque).
A vous de faire preuve d'imagination pour développer ces applications !


Commentaires
Bonjour, Votre article est très intéressant mais je n'arrive pas à voir comment tester C2DM lors du développement sans avoir à mettre notre application (non terminée) sur le market. En effet, lors des tests de développement, est-il possible d'essayer C2DM? Merci d'avance.
Alors throrin19, t'as trouvé si C2DM est testable sans mettre l'application sur le market ?
Salut ! Je suis aussi très intéressé par ta réponse thorin19, ou même clement si tu as trouvé toi aussi. Merci beaucoup pour votre aide.