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.
Share Button

17 Comments

  1. Mario Velasquez

    Buen día Belén, Gracias por este gran tutorial, me ha servido mucho.
    Ya mi app funciona y recibe los mensajes, pero cada vez que hago una actualización o desinstalo y vuelvo a instalar la app, los mensajes dejan de llegar, al ver el resultado del envío me muestra algo asi: {“multicast_id”:xxx,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”NotRegistered”}]}. según lo que he leido se puede implementar un método OnTokenRefresh pero no encuentro documentación sobre esto, Me podrías ayudar con un pequeño ejemplo de como usarlo y donde debo ubicarlo. Te agradezco muchísimo

    1. Belen

      Gracias por tu comentario. Lo primero comentar que si desinstalas la app, cuando la vuelves a instalar, la app debe registrarse de nuevo en el servicio. Lo segundo es que mi tutorial no está actualizado, ya que algunas cosas cambiaron y ya no se hacen de la misma forma. El método que comentas de onTokenRefresh debes crearlo en un servicio que debes crear, el cual extiende InstanceIDListenerService. Este servicio no estaban antes y por tanto, no lo explico en mi post.

  2. Juanma

    Excelente post Belén, es el mejor que he leido hasta la fecha de android y notificaciones push, enhorabuena.

    Me surge una duda, la clase GCMIntentService debo implementarla en un archivo de clases .java independiente o puedo implementarla en el archivo Principal de mi proyecto?

    Un saludo, gracias de antemano!

    1. Belen

      ¿Te refieres a que quieres implementarla en tu main activity? No deberías hacer eso. Crea un fichero nuevo sólo para esa clase, también por tener un buen diseño y arquitectura de tu código.

  3. Adrian

    tengo una duda cuando instalo y desinstalo la app recibo la notificacion duplicada no se como desactivar o elimnar los token con los que estan dado de algo he investigado pero nada no se si puedas ayudarme gracias. y si es asi aver si podrias darme un ejemplo

  4. Luis

    La teoría está muy bien explicada y ordenada a detalle, fue la primera página que seguí antes de darme cuenta de que estaba desactualizada, sólo una pregunta ya que aún no la actualizas.

    – Para la parte III: que permiso o servicio debo escribir para que la aplicación se mantenga viva, esperando los mensajes devuletos desde GSM, como el messenger de algunas redes sociales que se mantinen vivas, y te llegan notifcación, incluso si salí de ellas. Me dí cuenta de que a veces no llegan las notificaciones; revise código en el servidor, código en android y no encontraba el problema y revisando en “Config” => “Administrar aplicaciones” en información de la aplicación, la aplicación estaba cerrada, creo que sólo le llegan las notificaiones cuando está en ejecución.

    1. Belen

      Una de las características de GCM es que no necesitas tener tu app abierta para recibir las notificaciones. Por tanto, en este sentido no puedes controlar cuándo el sistema recibe una notificación. Tampoco debes intentar que tu app esté siempre ejecutándose. Android decide qué apps matar y cuáles no, según las necesidades del sistema. Sería mala práctica intentar que tu app esté siempre en ejecución.

  5. Antonio

    Hola, Belén.

    Agradecerte la ayuda que me has brindado con este completo tutorial.

    Tengo una duda, ¿dónde, en qué archivo, he de colocar el código que expones en esta cuarta parte del tutorial?

    Gracias de antemano.

    Saludos.

    1. Belen

      Muchas gracias, aunque ha quedado desactualizado. El código de la cuarta parte viene descrito en el texto dónde puede colocarse: “el código necesario para el registro de la aplicación a GCM lo insertaremos en el método onCreate de nuestra Activity principal.”

  6. Rafael Jimenez

    Buen día una pregunta no entendi muy bien de donde salio la clase GCMRegistrar espero me puedas explicar o es una clase que hiciste tu pero si es asi que se hace dentro de esa clase saludos

      1. Gonzalo

        Buenas, lo primero agradecerte el trabajo del blog, está muy bien explicado todo y facilita mucho las cosas

        Por otro lado me me preguntaba si podrías en un futuro dedicar algo de tiempo a modificar (o crear un nuevo manual) de cómo registrar el servicio GCM con la nueva API, ya que por un lado no tiene los mismos métodos que la API obsoleta, y por otro lado es algo más confusa.

        De nuevo agradecerte el manual y todo tu trabajo.

        Un saludo

    1. Belen

      se capturan dentro del método onError(Context context, String errorId) de la siguiente forma:

      if (errorId.equals(GCMConstants.ERROR_ACCOUNT_MISSING) {

      } else if (errorId.equals(GCMConstants.ERROR_SERVICE_NOT_AVAILABLE)) {

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Time limit is exhausted. Please reload the CAPTCHA.