Google Cloud Messaging. Parte IV: Aplicación cliente

The Google Cloud Messaging (GCM) guide can be found here and is available in English, therefore I am writing these related posts in Spanish.

Esta es la parte IV de un conjunto de entradas sobre Google Cloud Messaging (GCM).


En la publicación anterior comenzamos a ver la aplicación Android cliente: la instalación de la librería GCM y la configuración del fichero AndroidManifest.xml. En esta parte vamos a terminar de mostrar la aplicación cliente viendo la parte de programación.
Necesitamos implementar básicamente tres acciones:

  • Registro del servicio GCM
  • Borrado del registro del servicio
  • Recepción de los mensajes

Registro y borrado del servicio

Lo más normal es que queramos que nuestra aplicación se registre al comienzo de su ejecución, sin que sea necesaria interacción por parte del usuario. Por este motivo, el código necesario para el registro de la aplicación a GCM lo insertaremos en el método onCreate de nuestra Activity principal. Según los requerimientos de cada aplicación, puede realizarse el registro de forma diferente.

import com.google.android.gcm.GCMRegistrar;
...

try{

   GCMRegistrar.checkDevice(this);
   GCMRegistrar.checkManifest(this);

   final String regId = GCMRegistrar.getRegistrationId(this);

   if (regId.equals("")) {
      GCMRegistrar.register(this, SENDER_ID);
   } else {
      Log.v(TAG, "Ya estoy registrado");
   }

} catch (UnsupportedOperationException e) {
   Log.e(TAG, "El dispositivo no soporta GCM.", e);
} catch (IllegalStateException e) {
   Log.e(TAG, "El manifest no está bien configurado.", e);
}

En la línea 6 comprobamos si el dispositivo soporta GCM, de lo contrario saltará una excepción que debemos capturar.
En la línea 7 se comprueba si el archivo AndroidManifest.xml está bien configurado, por lo que una vez sepamos que está correcto, podemos quitar esta llamada. Igualmente debemos tratar la posible excepción que nos saltará si la configuración está mal.
En la línea 9 buscamos el Registration ID. En el caso de que no exista, es porque aún no nos hemos registrado.
El registro se realiza en la línea 12 donde pasamos como parámetro nuestro Sender ID.

Si recordamos el proceso del servicio de GCM, en el registro debíamos indicar el Sender ID y el Application ID. El Sender ID está contenido en la constante SENDER_ID y el Application ID es tomado automáticamente por la librería de GCM. El Sender ID se obtiene desde la consola de Google APIs tal y como expliqué en la parte II.


Para borrar el registro, llamamos al método unregister.

GCMRegistrar.unregister(this);

Podemos crear una vista de configuración donde el usuario pueda desactivar las notificaciones.

Servicio receptor

Finalmente tenemos que implementar la lógica de nuestro cliente cuando le lleguen los eventos. Con el uso de la librería GCM para Android tan sólo tenemos que crear el servicio que declaramos en el manifest llamado GCMIntentService. Esta clase tiene que extender la clase base que nos proporciona la librería GCM, GCMBaseIntentService. Al extenderla podemos añadir automáticamente los métodos a implementar.

import com.google.android.gcm.GCMBaseIntentService;

public class GCMIntentService extends GCMBaseIntentService {

   @Override
   protected void onError(Context context, String errorId){
      // Error en el registro: tratamiento del error
   }

   @Override
   protected void onMessage(Context context, Intent intent){
      // Notificación recibida: informo al usuario u otra acción	
   }

   @Override
   protected void onRegistered(Context context, String regId){
      // Registro correcto: envío el regId a mi servidor	
   }

   @Override
   protected void onUnregistered(Context context, String regId){
      // Borrado correcto: informo a mi servidor
   }
}

Es tan sencillo como añadir la lógica de nuestra aplicación a estos cuatro métodos:

  • onError.
    Este método es llamado cuando intentamos registrarnos o borrarnos del servicio de GCM pero se recibe un error.
  • onMessage.
    Este método es llamado cuando los servidores de GCM envíen un mensaje al dispositivo (previo envío del mensaje de nuestro servidor a los servidores de GCM). Si el mensaje contiene datos, éstos están contenidos como extras en el intent:

    String mensaje = intent.getStringExtra("mensaje");
    
  • onRegistered.
    Este método es llamado cuando tras una solicitud de registro, se recibe el Registration ID asignado por GCM. Recordamos que este identificador debe ser enviado y almacenado en nuestro servidor.
  • onUnregistered.
    Este método es llamado cuando el dispositivo se da de baja del servicio de GCM. Debe informarse a nuestro servidor para que también lo elimine.

Los errores que pueden recibirse en el método onError se encuentran como constantes en la clase GCMConstants de la librería GCM:

  • ERROR_ACCOUNT_MISSING.
    No hay cuenta de Google asociada en el dispositivo. Nuestra aplicación debería pedir al usuario que añada una cuenta desde el gestor de cuentas en los ajustes del dispositivo.
  • ERROR_AUTHENTICATION_FAILED.
    La contraseña de la cuenta de Google es incorrecta. Nuestra aplicación debería pedir al usuario que introdujese su contraseña desde el gestor de cuentas.
  • ERROR_INVALID_PARAMETERS.
    La petición enviada por el dispositivo no contiene los parámetros que eran esperados. El dispositivo no soporta GCM.
  • ERROR_INVALID_SENDER.
    No se reconoce el Sender ID. En este caso debemos revisar bien el Sender ID que estamos usando en nuestra aplicación, y comprobar que coincide con el que obtuvimos en la consola de Google APIs.
  • ERROR_PHONE_REGISTRATION_ERROR.
    Registro incorrecto del dispositivo. El dispositivo no soporta GCM.
  • ERROR_SERVICE_NOT_AVAILABLE.
    El dispositivo no pudo leer la respuesta, o el servidor GCM devolvió un código 500/503. No es un error de nuestra aplicación, por lo que deberemos reintentarlo más tarde.

Leer Más

Google Cloud Messaging. Parte III: Aplicación cliente

The Google Cloud Messaging (GCM) guide can be found here and is available in English, therefore I am writing these related posts in Spanish.

Esta es la parte III de un conjunto de entradas sobre Google Cloud Messaging (GCM).


Los pasos que vamos a seguir en nuestra aplicación Android para que juegue el rol de cliente y reciba los mensajes de nuestro servidor son los siguientes:

  • Instalar la librería de GCM.
  • Añadir los permisos al archivo “AndroidManifest.xml”.
  • Implementar el código para registrarse al servicio (y darse de baja).
  • Implementar el código del servicio que va a recibir los intents.

En esta parte sobre GCM, vamos a entrar en detalle sobre los dos primeros puntos. Los dos últimos se expondrán en la siguiente parte.

Librería GCM

En este tutorial vamos a instalar una librería adicional en nuestro SDK de Android que nos va facilitar la implementación del cliente de GCM. Puede realizarse igualmente sin el uso de esta librería, pero el código es mucho más sencillo e intuitivo haciendo uso de ella.

Abrimos el SDK Manager y en la sección de “Extras” seleccionamos “Google Cloud Messaging for Android Library”.

SDK manager

La instalamos y tras finalizar, en el directorio donde tenemos la instalación del SDK, dentro de la ruta “/extras/google/” se ha creado la carpeta llamada “gcm” que a su vez contiene las carpetas “gcm-client”, “gcm-server” y “samples”. Dentro del directorio “gcm-client/dist” encontramos el archivo “gcm.jar”, el cual debemos importar en nuestra aplicación.

Actualización!!

El paquete de GCM ya no se encuentra como “Google Cloud Messaging for Android Library”, ahora forma parte de “Google Play services” que se encuentra también en la sección de “Extras”.

Para saber cómo añadir Google Play Services a vuestro proyecto podéis seguir la guía oficial aquí.

 

Android Manifest

El siguiente paso que podemos seguir, es modificar el archivo “AndroidManifest.xml” para configurarlo correctamente.

  • Si el uso de GCM es imprescindible para nuestra aplicación, debemos establecer la mínima versión del SDK, a la 8, es decir, Android 2.2.
    <uses-sdk android:minSdkVersion="8" ... />
  • Añadimos permisos para evitar que otras aplicaciones se registren y reciban los mensajes de nuestra aplicación. Debemos especificar el mismo nombre que el del paquete de nuestra aplicación (que se encuentra también indicado en el propio manifest).
    <permission android:name="my_pack.permission.C2D_MESSAGE"
       android:protectionLevel="signature"/>
    <uses-permission android:name="my_pack.permission.C2D_MESSAGE"/>
  • Añadimos el resto de permisos.
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    

    “GET_ACCOUNTS” nos permite acceder a la cuenta de Google del dispositivo, la cual es necesaria si la versión instalada es inferior a Android 4.0.4.

  • Dentro de la etiqueta “application” añadimos el receptor o cliente de los mensajes. Son 2 intents los que pueden recibirse del GCM: “REGISTRATION” y “RECEIVE”.
    Gracias a que estamos usando la librería de GCM para Android, no tenemos que implementar nuestra propia clase cliente, sino que usamos la que la librería nos proporciona com.google.android.gcm.GCMBroadcastReceiver.

    <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="my_pack" />
      </intent-filter>
    
    </receiver>
    

    Se debe declarar de esta forma, y no mediante programación, para que los mensajes sean recibidos incluso si la aplicación no se está ejecutando.
    El permiso “SEND” se incluye para que tan sólo se reciban intents provenientes de los servidores GCM.

  • Añadimos un servicio cuyo nombre debe ser “GCMIntentService”. Este nombre es al que se llama desde el receptor anterior. Este servicio sí tenemos que implementarlo con nuestras propias acciones.
    <service android:name=".GCMIntentService"/>

Leer Más