Programación Android, NotificationManager y NotificationCompat II

Share if you like...Share on Facebook0Tweet about this on TwitterShare on Google+0Share on LinkedIn0

Hace un par de meses explicamos cómo mostrar notificaciones en Android, sin embargo el ejemplo se quedó a la espera de completar los parámetros de la notificación para abrir la aplicación y añadiendo un BroadcastReceiver que también lance la notificación.

En primer lugar vamos a explicar el código que necesitamos para lanzar la aplicación al pulsar la notificación, sobre la notificación que ya creamos para nuestro Service. Para hacer esto necesitamos, en primer lugar, crear un Intent que llame a la Activity que queremos abrir. Posteriormente crearemos un PendingIntent que será el que contenga la configuración que necesitamos para que cuando pulsemos la notificación se comporte como queremos, abriendo la Activity que hemos indicado en el Intent.

Como el término PendingIntent es la primera vez que aparece por aquí, antes de crearlo vamos a explicar qué es y qué hace. Este objeto es el que permite a componentes externos a nuestra aplicación, generalmente desarrollados por terceros, que ejecuten un trozo de código que nosotros indicamos, en este caso su utilidad será la de permitir que el NotificationManager sea capaz de lanzar el Intent que nosotros hemos configurado. Para dar una idea más sencilla de lo que hace un PendingIntent, se puede entender como un Intent que se manda al sistema, pendiente de una ejecución futura, pero de la que desconocemos cuándo se producirá.

Para obtener el PendingIntent, en nuestro ejemplo, lo haremos de dos formas distintas, utilizando métodos estáticos de la clase PendingIntent. La primera forma es la que vamos a utilizar para nuestro Service, a través del método PendingIntent.getActivity(), y la segunda la utilizaremos en nuestro BroadcastReceiver, a través del método PendingIntent.getBroadcast(). Veamos a continuación cómo añadirlo al código de nuestro Service. Después de crear nuestro objeto Builder de la notificación, pero antes de mandarla al sistema, añadimos el siguiente código:

// Creamos el Intent que llamará a nuestra Activity
Intent targetIntent = new Intent(getBaseContext(),
		MainActivity.class);
// Creamos el PendingIntent
PendingIntent contentIntent = PendingIntent.getActivity(
		getBaseContext(), 0, targetIntent,
		PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);

builder.setAutoCancel(true);

En primer lugar nos fijaremos en cómo hemos creado el PendingIntent. Vemos que el método getActivity recibe 4 parámetros:

  • Context: El contexto en que se crea el PendingIntent, nos lo facilita el método getBaseContext.
  • RequestCode: En este caso no necesitamos ningún código de respuesta, por lo tanto pasamos 0.
  • Intent: El Intent que se lanzará cuando se ejecute el PendingIntent.
  • int: Banderas que indican el comportamiento del PendingIntent. Pasamos PendingIntent.FLAG_UPDATE_CURRENT que indica que se actualizará la información del PendingIntent en el caso de que se lance uno y ya existiera previamente.

Por último, para asignar el PendingIntent a nuestra notificación, lo hacemos mediante el método setContentIntent del builder, y posteriormente indicamos que nuestra notificación se cancelará a si misma en caso de que se pulse sobre ella con el método setAutoCancel.

Con esto ya habremos completado nuestra notificación en el Service, ahora nos falta añadir un BroadcastReceiver y configurar en él también nuestra notificación.

Vamos a utilizar el BroadcastReceiver que creamos cuando explicamos su uso, añadiéndolo a este proyecto, y una vez añadido abrimos nuestro BroadcastReceiver y, en lugar de mostrar el Toast que tiene configurado, lo eliminaremos y crearemos una nueva notificación en el método onReceive:

@Override
public void onReceive(Context ctx, Intent i) {
	NotificationManager nManager = (NotificationManager) ctx
			.getSystemService(Context.NOTIFICATION_SERVICE);

	NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx)
			.setSmallIcon(android.R.drawable.ic_dialog_info)
			.setContentTitle("BroadcastReceiver")
			.setContentText("Se ha conectado el cargador.")
			.setWhen(System.currentTimeMillis());

	Intent targetIntent = new Intent(ctx, MainActivity.class);
	PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
			targetIntent, PendingIntent.FLAG_UPDATE_CURRENT);
	builder.setContentIntent(contentIntent);

	builder.setAutoCancel(true);

	nManager.notify(123456, builder.build());

}

En general podemos ver que el código es prácticamente el mismo que en el ejemplo del Service, salvo las siguientes modificaciones:

  • Para acceder al servicio del sistema, la clase BroadcastReceiver no tiene acceso directo, por lo tanto lo hacemos a través del Context que nos viene en onReceive.
  • No tenemos acceso tampoco al Context a través del método getBaseContext, que no existe en el BroadcastReceiver, sin embargo utilizamos el contexto que nos viene en onReceive.
  • Cambiamos el texto del título y del contenido, para diferenciar el Service del BroadcastReceiver.
  • Cambiamos la ID de la notificación, para que sea distinta de la del Service.

Por último, podemos ver que, tras terminar la tarea programada para el Service y conectar el cargardor, se nos mostrarán las 2 notificaciones en la barra de notificaciones, y al pulsar cada una, desaparecerá e iniciará nuestra aplicación:

Notificaciones
Notificaciones de BroadcastReceiver y Service

Descargas

Puedes descargar el proyecto completo aquí.

Share if you like...Share on Facebook0Tweet about this on TwitterShare on Google+0Share on LinkedIn0
The following two tabs change content below.
Reborn as IT Developer. Desarrollador Android y fundador de Proyecto Simio. "En realidad, yo no puedo enseñar nada a nadie, sólo puedo hacerles pensar." - Sócrates.

14 thoughts on “Programación Android, NotificationManager y NotificationCompat II

  1. Buenas noches lo primero gracias por el código.

    Me ha sido muy útil (pues poseo una pantalla de carga de entre 15 y 90 segundos en mi aplicación y me gusto mucho lo de la notificación. Pero me surgen 2 problemas:

    1 al pulsar la notificación me vuelve a Crear la activity y me vuelve a mandar notificación eternas veces xDDD
    2 antes de la notificación cuando cargaba la nueva Activity se ponia en primer plano sola, aunque estuviera en otra cosa del móvil, pero no era efectivo en los Android 4.04 (O por lo menos NO en mi Samsung Trend) si soluciono el bucle de notificaciones… como puedo hacerque esa pantalla no salga a primer plano.

    Muchas gracias por adelantado.

  2. Hola, y cómo puedo hacer para abrir otra actividad en vez de que se abra la principal, ya que en la notificaion quiero que se abra la actividad Version.class. pero cuando la aplicacion esta cerrada me llega la notificacion y le doy tap, pero me manda al MainActivity.class en vez de Version.class

    1. En la línea:

      Intent targetIntent = new Intent(getBaseContext(),
              MainActivity.class);
      

      Modifica “MainActivity.class” por la activity que quieras iniciar.

      Un saludo.

  3. Buenas!!!

    Muy bien explicado, enhorabuena.

    Tengo una duda. Con el PendingIntent entiendo que podemos capturar las notificaciones externas de nuestra aplicación, como whatsapp, por ejemplo. ¿Pero también podríamos modificar el acceso de los terceros a la barra de notificaciones? Por ejemplo, hacer una aplicación que capture las notificaciones de whatsapp y cancele la entrada a las notificaciones de mensajes pertenecientes a grupos.

    O hay alguna manera de controlar las aplicaciones de terceros desde una aplicación propia.

    Muchas gracias de antemano!!!!

    1. Para hacer ese tipo de cosas tendrías que tener permiso del sistema (el usuario tiene que activarlo específicamente para tu aplicación). Y aún teniendo ese permiso para acceder a las notificaciones desconozco si podrías eliminar esa notificación.

      Un saludo!

  4. Hola , como estas estoy intentando programar alarmas q creen notificaciones a una hora especifica del dia, pero tengo problemas pues no esta haciendolo en esos instantes, sino cuando abro la applicacion. Tengo una semana y no se como lograr que efectivamente por ejemplo lance la notificacion a las 2:00pm todos los dias. Gracias

    1. Buenas Alicia,

      Lo que necesitas es utilizar el AlarmManager para programar alarmas, sin embargo en kitkat no necesariamente se va a lanzar a la hora exacta en la que lo programes (reconocido por Google), y además si se apaga el dispositivo desaparecerá la alarma, por lo que al encender de nuevo el dispositivo tendrías que tener un BroadcastReceiver que recogiera el evento de encendido y volver a programar así la alarma. La documentación del AlarmManager la tienes aquí: http://developer.android.com/reference/android/app/AlarmManager.html

      1. Me da a mi que quiere hacer un trigger que reciba por broadcast info de una tabla de mysql, en lugar de con un timer que vaya automatizado cada vez que se haga un update o un insert… o eso imagino…

        Por cierto, muy buen tutorial. GRACIAS!

        1. Te recomiendo que no uses mysql en android, para eso esta sqlite, piensa que android fue diseñado para telefonos moviles con una pequeña cantidad de ram, procesador y bateria.
          Por otro lado como el insert o el update es por codigo no veo para que quieres usar un trigger.

Deja un comentario