23/05/2013
En el tip anterior vimos cómo hacer uso de las funcionalidades básicas del servicio de notificaciones, aplicables a cualquier versión de Android. En este tip vamos a ver las nuevas notificaciones «expandibles» que nos ofrece Jelly Bean y cómo utilizarlas en una app y que además pueda ejecutarse en versiones anteriores.
Vamos a reutilizar el ejemplo del tip anterior.. Necesitaremos incluir en nuestro proyecto la libreria de compatibilidad de Android para crear las notificaciones con NotificationBuilder. Hay que descargarla desde el SDK Manager, y la incluimos en nuestro proyecto en directorio libs como cualquier otra libreria de terceros (las plantillas para crear proyectos Android en Eclipse dan la opción de incluirla automáticamente). Además, ahora tendremos que compilar con la API 16 (Android 4.1.2) o superior.
En Jelly Bean tenemos tres estilos de notificaciones:
- BigPictureStyle: Pensadas para incluir una imagen de gran tamaño (hasta 256 dp)
- Notification.BigTextStyle:Muestra un texto largo usando las líneas que sean necesarias. En el ejemplo del tip anterior el mensaje de la notificación sólo ocupaba una línea.
- Notification.InboxStyle: Muestra una lista de cadenas (máximo 5)
Puesto que probaremos los tres tipos, ahora en nuestro layout vamos a utilizar tres botones. Quedará tal que así:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:orientation="vertical" > <Button android:id="@+id/button1" android:layout_width="150dp" android:layout_height="wrap_content" android:onClick="bigPicture" android:text="@string/bigPicture" /> <Button android:id="@+id/button2" android:layout_width="150dp" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:onClick="bigText" android:text="@string/bigText" /> <Button android:id="@+id/button3" android:layout_width="150dp" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:onClick="inbox" android:text="@string/inbox" /> </LinearLayout>
El código de cada botón es siempre el mismo y tan sólo cambia el tipo de notificación y su configuración correspondiente por lo que lo voy a abstraerlo casi todo en un mérodo privado. La Activity comentada es la siguiente:
package com.danielme.tipsandroid.notificacionesjb; import android.annotation.SuppressLint; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat.Builder; import android.view.View; import android.widget.Toast; /** * * @author danielme.com * */ @SuppressLint("NewApi") public class MainActivity extends Activity { private static final String DESDE_NOTIFICACION = "desdeNotificacion"; private static final int BIG_PICTURE = 1; private static final int BIG_TEXT = 2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (getIntent().getExtras() != null) { boolean mostrarToast = getIntent().getExtras().getBoolean(DESDE_NOTIFICACION, false); if (mostrarToast) { Toast.makeText(this, R.string.desdeNoti, Toast.LENGTH_SHORT).show(); } } } public void bigPicture(View view) { mostrarNotificacion(BIG_PICTURE); } public void bigText(View view) { mostrarNotificacion(BIG_TEXT); } public void inbox(View view) { mostrarNotificacion(0); } private void mostrarNotificacion(int type) { NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); //intent hacia la activity que se ejecutará cuando se pulse la notificación. Enviamos un parámetro para saber que llegamos //a la activity desde la notificación y mostrar un Toast Intent notificacionIntent = new Intent(getApplicationContext(), MainActivity.class); notificacionIntent.putExtra(DESDE_NOTIFICACION, true); PendingIntent notificacionPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificacionIntent, 0); //usamos siempre el builder de la libreria de compatibilidad y no el de Jelly Bean Builder builder = new NotificationCompat.Builder(this); //titulo de la notificación builder.setContentTitle(getString(R.string.titulo)) //mensaje que aparece en la barra de estado al efectuarse la notificación .setTicker(getText(R.string.ticker)) //icono que se muestra en la barra de estado, debe ser de muy pequeño tamaño para que se vea entero .setSmallIcon(R.drawable.small) //icono que se muestra dentro de la notificación .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)) //el texto con el contenido, sólo se mostrará si no estamos en Jelly Bean y por lo tanto no se puede aplicar el estilo .setContentText(getString(R.string.contenido)) .setContentIntent(notificacionPendingIntent); Notification notificacion = null; if (type == BIG_PICTURE) { //mostramos uno de los walppaper por defecto de Ubuntu 😉 notificacion = new NotificationCompat.BigPictureStyle(builder) .bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.delicate_petals_ubuntu_wallpaper)).build(); } else if (type == BIG_TEXT) { notificacion = new NotificationCompat.BigTextStyle(builder) .bigText(getText(R.string.lorem)).build(); } else { //cuatro líneas y una quinta con un separador. el texto dbe ser muy corto pues no hay saltos notificacion = new NotificationCompat.InboxStyle(builder) .addLine(getText(R.string.primera)).addLine(getText(R.string.segunda)) .addLine(getText(R.string.tercera)).addLine(getText(R.string.cuarta)) .setSummaryText(getText(R.string.quinta)).build(); } //el atributo flags de la notificación nos permite ciertas opciones notificacion.flags |= Notification.FLAG_AUTO_CANCEL;//oculta la notificación una vez pulsada //idem para defaults notificacion.defaults |= Notification.DEFAULT_SOUND; //sonido //añadimos efecto de vibración, necesitamos el permiso <uses-permission android:name="android.permission.VIBRATE" /> notificacion.defaults |= Notification.DEFAULT_VIBRATE; notificationManager.notify(0, notificacion); } }
El resultado en Jelly Bean es el siguiente:
Gracias a la libreria de compatibilidad, la aplicación de ejemplo funciona en versiones anteriores a Jelly Bean pero no se aplican los estilos y siempre se muestra el texto indicado en el método setContentText. Así pues, el resultado es el mismo que obtenemos en el tip anterior. En la siguiente imagen vemos la notificación en Android 4 y Android 2.1 para cualquiera de los estilos que seleccionemos.
El proyecto completo para Eclipse ADT se encuentra en Github. Para más información sobre cómo utilizar GitHub, consultar este artículo.