Empezando con las Notificaciones Push en Android
() translation by (you can also view the original English article)
Introducción
Conseguir que los usuarios instalen tu app es sólo una victoria a medias. Conseguir que la usen con regularidad es la otra mitad. Es muy posible que tus usuarios se olviden completamente de la app tras usarla un par de veces. Estará compitiendo por su atención con muchas otras apps nuevas.
Usando las notificaciones push, puedes mandar recordatorios de vez en cuando, mejorando las posibilidades de que tu app permanezca instalada en sus dispositivos.
Google Cloud Messaging, abreviado GCM, es un servicio gratuito que puedes usar para enviar notificaciones a tus usuarios. En este tutorial vas a aprender a usarlo para crear una app Android que recibirá notificaciones push, y un sencillo script en Python como servidor para crearlas y enviarlas.
Porque usar Google Cloud Messaging?
En la mayoria de las comunicaciones cliente-servidor, el cliente inicia las peticiones para recibir datos del servidor. En otras palabras, el cliente es quien pide datos al servidor. En el caso de las notificaciones push, en cambio, es el servidor el que inicia la tranferencia de datos.
Esto generalmente se logra manteniendo una conexión persistente de tipo TCP/IP — una conexión que permanece abierta indefinidamente — entre el servidor y el cliente. Puede parecer estupendo, pero si tienes una app popular, mantener miles de conexiones persistentes entre tu servidor y los dispositivos de tus usuarios puede resultar muy caro.
Google Cloud Messaging es un servicio que resuelve este problema actuando como un intermediario entre el servidor y los dispositivos de tus usuarios. Con GCM, el Cloud Connection Server de Google, abreviado CCS, gestiona las conexiones persistentes por ti. También se asegura de que tus notificaciones push sean enviadas de forma segura.
Prerrequisitos
Para seguir este tutorial, necesitas:
- La última versión de Android Studio
- Python 2.7.6 o superior
- Un dispositivo con Android 4.4 o superior, con Google Play Services instalado
1. Configurando el proyecto en Android Studio
Inicia Android Studio y crea un proyecto nuevo con una Activity
vacia. Si has usado la configuración por defecto, el proyecto debería incluir una clase java en MainActivity.java.
Paso 1: Añade las Dependencias
En este proyecto, utilizaremos el plugin de gradle Google Services para configurar GCM. Incluyelo en el proyecto añadiendo la siguiente línea en la sección de dependencies
del archivo build.gradle:
1 |
classpath 'com.google.gms:google-services:1.5.0' |
A continuación, aplica el plugin en el módulo app
de build.gradle:
1 |
apply plugin: 'com.google.gms.google-services' |
Para poder usar la API de GCM, añade com.google.android.gms:play-services
como una dependencia compile
en el mismo archivo:
1 |
compile "com.google.android.gms:play-services:8.3.0" |
Si pulsas en Sync Now, deberías ver el siguiente error:



Haga clic en el enlace Install Repository and sync project para corregir el error.
Paso 2: Actualizar el Manifiesto
Dentro del archivo del proyecto AndroidManifest.xml, crea y usa un permiso personalizado de tipo C2D_MESSAGE basado en el nombre del paquete del proyecto. Asegúrate de que el protectionLevel
del permiso está establecido en signature.
1 |
<permission
|
2 |
android:name="com.github.hathibelagal.pn.permission.C2D_MESSAGE" |
3 |
android:protectionLevel="signature" /> |
4 |
<uses-permission
|
5 |
android:name="com.github.hathibelagal.pn.permission.C2D_MESSAGE" /> |
Las notificaciones se reciben en forma de broadcasts. Para controlar esas emisiones, la aplicación necesita un BroadcastReceiver
. Sin embargo, no tenemos que crearlo manualmente. En su lugar podemos utilizar la clase GcmReceiver
para que haga de BroadcastReceiver
.
El BroadcastReceiver
debe tener un intent-filter
que responde a la acción de com.google.android.c2dm.intent.RECEIVE
y el nombre de su category
debe coincidir con del paquete del proyecto. Añade el siguiente código al manifiesto:
1 |
<receiver
|
2 |
android:name="com.google.android.gms.gcm.GcmReceiver" |
3 |
android:exported="true" |
4 |
android:permission="com.google.android.c2dm.permission.SEND" > |
5 |
<intent-filter>
|
6 |
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> |
7 |
<category android:name="com.github.hathibelagal.pn" /> |
8 |
</intent-filter>
|
9 |
</receiver>
|
2. Consigue una Server API Key y un Sender ID
Para comunicarnos con el Cloud Connection Server, necesitamos identificarnos usando una API key en el lado del servidor y un sender ID en el lado del cliente. Para obtener ambos, crea un proyecto nuevo en la consola de desarrolladores.



Empieza haciendo click en el boton Pick a platform. A continuación, haz click en el botón Enable services for my Android App. Al hacerlo, se te pedirá que des un nombre de aplicación y el nombre del paquete Android de la app Asegúrate de que en nombre del paquete Android que das coincide con el nombre de paquete que escribiste al crear el proyecto en Android Studio.



A continuación, haz click abajo en el botón Choose and configure services. Ahora puedes seleccionar los servicios de Google que quieres añadir a la aplicación.



Por ahora, haz clic en el botón Cloud Messaging y después en Enable Google Cloud Messaging. Después de unos segundos, te aparecerá tu API key server y sender ID. Apunta la server API key y pulsa Close.



El plugin Google Services que hemos añadido anteriormente necesita un archivo de configuración para funcionar correctamente. Crea el archivo haciendo clic en el botón Generate configuration files.
Cuando el archivo haya sido generado, descárgalo y colócalo en la carpeta del proyecto de Android Studio de tu app.
3. Registrando el Cliente
GCM identifica los dispositivos Android mediante fichas de registro ('tokens'). Por lo tanto, nuestra app debe poder registrarse desde cada dispositivo Android en el que esté instalada.
Paso 1: Crear un Servicio de Registro
El proceso de registro debe ejecutarse en un hilo secundario porque puede tardar unos momentos, dependiendo de la conectividad de la red. Como el proceso de registro no necesita ninguna interacción del usuario, un IntentService
es una opción ideal.
Crea una nueva clase Java llamada RegistrationService.java, hazla una subclase de IntentService
, y sobreescribe su método onHandleIntent
.
1 |
public class RegistrationService extends IntentService { |
2 |
public RegistrationService() { |
3 |
super("RegistrationService"); |
4 |
}
|
5 |
|
6 |
@Override
|
7 |
protected void onHandleIntent(Intent intent) { |
8 |
|
9 |
}
|
10 |
}
|
Dentro del método onHandleIntent
, podemos usar la Instance ID API para generar o descargar el 'token' de registro Primero, crea una instancia de la clase InstanceID
, usando el método getInstance
.
1 |
InstanceID myID = InstanceID.getInstance(this); |
Ahora podemos usar el método getToken
del objeto InstanceID
para obtener el 'token' de registro en forma de String
. getToken
necesita tener el sender ID como uno de sus argumentos. Al haber añadido el archivo google-services.json al proyecto, podemos pasar el sender ID al método usando R.string.gcm_defaultSenderID
.
1 |
String registrationToken = myID.getToken( |
2 |
getString(R.string.gcm_defaultSenderId), |
3 |
GoogleCloudMessaging.INSTANCE_ID_SCOPE, |
4 |
null
|
5 |
);
|
Si quieres ver el contenido del 'token' de registro para depuración, puedes crear un log de depuración usando el método Log.d
.
1 |
Log.d("Registration Token", registrationToken); |
En este punto, puedes enviar el 'token' de registro a tu servidor web y guardarlo allí en una base de datos. Sin embargo, no necesitas hacerlo si no piensas dirigirte a tus usuarios de forma individual. Si vas a mandar el mismo mensage a cada usuario, deberías seguir el enfoque publicar-suscribir.
Ahora te voy a mostrar como suscribirte a un topic
(tema) llamado my_little_topic. Sólo requiere dos líneas de código. Primero, crea una nueva instancia de la clase GcmPubSub
usando su método getInstance
. A continuación, llama a su método subscribe
pasándole el 'token' de registro y el nombre del tema.
1 |
GcmPubSub subscription = GcmPubSub.getInstance(this); |
2 |
subscription.subscribe(registrationToken, "/topics/my_little_topic", null); |
Nuestra aplicación ya puede recibir cada notificación push publicada con my_little_topic.
para terminar, define el servicio en AndroidManifest.xml.
1 |
<service android:name=".RegistrationService" |
2 |
android:exported="false" /> |
El servicio de registro está completo.
Paso 2: Crear una InstanceIDListenerService
Los 'tokens' de registro se actualizan cada dia. Por eso, cada app Android que use GCM debe tener una InstanceIDListenerService
que gestione esas actualizaciones. Para ello, crea un nuevo archivo Java llamado TokenRefreshListenerService.java, y hazlo una subclase de InstanceIDListenerService. Dentro del método onTokenRefresh de dicha clase, todo lo que hay que hacer es inicializar el proceso de registro de nuevo, lanzando el servicio de registro usando un Intent y el método startService.
Añade el siguiente código a TokenRefreshListenerService.java:
1 |
public class TokenRefreshListenerService extends InstanceIDListenerService { |
2 |
@Override
|
3 |
public void onTokenRefresh() { |
4 |
Intent i = new Intent(this, RegistrationService.class); |
5 |
startService(i); |
6 |
}
|
7 |
}
|
Éste servicio debe poder responder a la acción com.google.android.gms.iid.InstanceID
. Por eso, al definir el servicio en AndroidManifest.xml, añade el intent-filter
apropiado.
1 |
<service
|
2 |
android:name=".TokenRefreshListenerService" |
3 |
android:exported="false"> |
4 |
<intent-filter>
|
5 |
<action android:name="com.google.android.gms.iid.InstanceID" /> |
6 |
</intent-filter>
|
7 |
</service>
|
Paso 3: Lanzando el Servicio de Registro
Para estar seguro de que el proceso de registro comienza nada mas abrir la app, debemos inicializar la clase RegistrationService
dentro del método onCreate
de la MainActivity
. Para ello, crea un Intent
y usa el método startService
.
1 |
Intent i = new Intent(this, RegistrationService.class); |
2 |
startService(i); |
4. Mostrando las Notificaciones Push
GCM muestra automaticamente las notificaciones push en la bandeja de notificaciones tan pronto como son recibidas. Pero sólo lo hace si la app asociada contiene un GCMListenerService
.
Crea una nueva clase Java llamada NotificacionsListenerService y hazla una subclase de GCMListenerService
. A menos que quieras gestionar los datos enviados tú mismo, no necesitas escribir nada dentro de esta clase. De momento podemos dejar esta clase vacía.
1 |
public class NotificationsListenerService extends GcmListenerService { |
2 |
|
3 |
}
|
Al definir el servicion en el AndroidManifest.xml, asegúrate de que añades un intent-filter
que le permita responder a la acción com.google.android.c2dm.intent.RECEIVE
.
1 |
<service
|
2 |
android:name=".NotificationsListenerService" |
3 |
android:exported="false" > |
4 |
<intent-filter>
|
5 |
<action android:name="com.google.android.c2dm.intent.RECEIVE" /> |
6 |
</intent-filter>
|
7 |
</service>
|
5. Añadiendo Iconos a las Notificaciones Push
Cada notificacion push debe tener un icono asociado a ella. Si no tienes ninguno a mano, puedes obtenerlo de la librería de Google Material Design Icons.



Una vez que hayas descargado el icono, colócalo en la carpeta res de tu proyecto Yo usaré el icono ic_cloud_white_48dp.
6. Lanzando la App
Nuestra app Android ya está completa. Cuando la compiles y la ejecutes en un dispositivo Andorid, podrás ver el 'token' de registro en la ventana de logcat.



Pulsa el botón 'atrás' en tu dispositivo para salir de la app. Esto es necesario porque GCM mostrará las notificaciones push automáticamente sólo si el usuario no está usando la app. Si quieres que las notificaciones se muestren incluso cuando la app se está ejecutando, tendrás que crear las notificaciones tú mismo en NotificationsListenerService
usando la clase Notification.Builder
.
7. Enviando Notificaciones Push
En la última parte de éste tutorial, crearemos un sencillo script en Python que pueda generar y enviar notificaciones push a todos los dispositivos Android en los que la app esté instalada.
Puedes ejecutar estre script desde tu ordenador local o desde un servidor web remoto en el que tengas acceso SSH.
Paso 1: Creando el Script
Crea un archivo nuevo llamado send.py y ábrelo usando tu editor de texto favorito.
En la primera línea, importa los módulos urllib2
y urllib
. Usaremos estos módulos to enviar datos al Cloud Connection Server de Google. Importa también el módulo json
porque éste será el formato en que enviaremos los datos. Finalmente, para tener acceso a los argumentos desde la línea de comandos, importa el módulo sys
.
1 |
from urllib2 import * |
2 |
import urllib |
3 |
import json |
4 |
import sys |
A continuación, crea una variable para almacenar la server API key que apuntaste antes. La 'key' debe formar parte de cada petición HTTP que hagamos al CCS.
1 |
MY_API_KEY="ABCDEF123456789ABCDE--12A" |
Cada notificación debe tener un campo title(titulo) y otro body(mensaje). En vez de escribirlos directamente en el script, los proporcionaremos como argumentos en la línea de comandos usando el array argv
.
1 |
messageTitle = sys.argv[1] |
2 |
messageBody = sys.argv[2] |
Crea un objeto nuevo de tipo diccionario Python para representar los datos que se enviarán al CCS. Para que nuestra app de Android pueda recibir la notificación, ésta debe publicarse con el tema my_little_topic. Por tanto, añade una 'key' llamada to al diccionario y pon su 'value' como /topics/my_little_topic.
Para representar los contenidos de la notificación, añade una 'key' llamada notification al diccionario y pon su 'value' como otro diccionario conteniendo tres 'keys':
- body
- title
- icon
Asegúrate de que el valor de la 'key' icon
coincide con el nombre del icono drawable en tu proyecto Android.
1 |
data={ |
2 |
"to" : "/topics/my_little_topic", |
3 |
"notification" : { |
4 |
"body" : messageBody, |
5 |
"title" : messageTitle, |
6 |
"icon" : "ic_cloud_white_48dp" |
7 |
}
|
8 |
}
|
Transforma el diccionario en un string JSON usando la función dumps
del módulo json
:
1 |
dataAsJSON = json.dumps(data) |
Todo lo que necesitamos hacer ahora es enviar el string JSON a https://gcm-http.googleapis.com/gcm/send. Para ello, creamos un nuevo objeto Request
y establecemos dataAsJSON
como sus datos. A continuación, establece el valor del header Authorization
en MY_API_KEY
y el header Content-type
en application/json.
1 |
request = Request( |
2 |
"https://gcm-http.googleapis.com/gcm/send", |
3 |
dataAsJSON, |
4 |
{ "Authorization" : "key="+MY_API_KEY, |
5 |
"Content-type" : "application/json" |
6 |
}
|
7 |
)
|
Finalmente, para ejecutar la petición y obtener la respuesta, pasa el objeto request a la función urlopen
y llama su método read
.
1 |
print urlopen(request).read() |
El script de Python está completo y listo para usarlo.
Paso 2: Ejecutando el Script
En este punto, estamos listos para enviar notificaciones push a todos los dispositivos en los que esté instalada nuestra app. Abre un terminal y ve al directorio en que creaste send.py.
Pasa el nombre del script al ejecutable python junto a un string como título de la notificación y otro como mensaje de la misma. Puedes usar este ejemplo:
1 |
python send.py "My first push notification" "GCM API is wonderful!" |
Si no hay errores, deberías obtener una respuesta como ésta:
1 |
{"message_id":12345676892321} |
Si compruebas tu dispositivo Android , deberías ver una nueva notificación en la bandeja de notificaciones.



Conclusión
Ahora ya sabes como enviar notificaciones push a tus usuarios. En esta lección, has aprendido a crear una app en Android capaz de registrarse a sí misma y recibir notificaciones que son publicadas sobre un tema específico. También has aprendido a crear un script en Python que puede publicar notificaciones.
Aunque las notificaciones push pueden parecer una forma genial de comunicarte con tus usuarios, te sugiero que las uses con moderación y solamente si tienes algo útil que decir, porque enviar demasiadas o con demasiada frecuencia es posiblemente la manera mas rápida de conseguir que tu app sea desinstalada.
Para aprender mas acerca de Google Cloud Messaging, echa un vistazo a la Cloud Messaging Guide.
¡Sé el primero en conocer las nuevas traducciones–sigue @tutsplus_es en Twitter!