DesarrolloLibre

Desarrollo Web, Android y mucho más

12-12-2016

En esta entrada veremos cómo crear una notificación personalizada desde Android.

¿A qué nos referimos con notificación personalizada?

A que emplearemos una vista desarrollada desde cero para tal fin; incluso emplearemos unos botones los cuales pueden ejercer sus acciones sobre la actividad, servicios o BroadCast; el código de la vista está un poco más adelante, pero por ahora indicaremos los primeros pasos para crear una notificación en Android.

        Intent intent = new Intent(getApplicationContext(), MusicService.class);
        noBundle.putInt("accion", 1);//This is the value I want to pass
        intent.putExtras(noBundle);
        PendingIntent pendingIntent = PendingIntent.getService(ListActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.ibAccion, pendingIntent);

Expliquemos para que es cada componente del código presentado anteriormente:

  • El Bundle Es empleado generalmente para pasar datos entre componentes como actividades y fragments.
  • El Intent Los intents son el componente empleado para iniciar la comunicación entre los componentes como inicar una actividad o servicio (más información en la documentación oficial).
  • El PendingIntent es un objeto que contiene a un intent; este objeto PendingIntent permite al NotificationManager mandar al sistema la acción a ejecutar (como abrir una actividad).

Muy importante la bandera PendingIntent.FLAG_UPDATE_CURRENT que en conjunto con:

        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:launchMode="singleTop"
            android:screenOrientation="portrait">
...
</activity>

Indicamos que la actividad existe actualmente (por defecto el MainActivity es la primera actividad que inició) y el android:launchMode="singleTop" y es una forma de indicar que la instancia de la actividad sea única, aunque existen otras formas como puedes consultar en el siguiente enlace (en otras palabras significa actualizar la instancia de la actividad que está en ejecución actualmente).

Cómo son tres botones, necesitamos tres Intents diferentes y todo lo que esto conlleva, por lo tanto ahora multiplicamos esto por tres:

        Intent intent = new Intent(getApplicationContext(), MusicService.class);
        noBundle.putInt("accion", 1);//This is the value I want to pass
        intent.putExtras(noBundle);
        PendingIntent pendingIntent = PendingIntent.getService(ListActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.ibAccion, pendingIntent);


        Bundle noBundle2 = new Bundle();
        noBundle2.putInt("accion", 2);//This is the value I want to pass
        Intent intent2 = new Intent(getApplicationContext(), ListActivity.class);
        intent2.putExtras(noBundle2);
        PendingIntent pendingIntent2 = PendingIntent.getActivity(ListActivity.this, 2, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.ibQuitar, pendingIntent2);


        Bundle noBundle3 = new Bundle();
        noBundle3.putInt("accion", 3);//This is the value I want to pass
        Intent intent3 = new Intent(getApplicationContext(), ListActivity.class);
        intent3.putExtras(noBundle3);
        PendingIntent pendingIntent3 = PendingIntent.getActivity(ListActivity.this, 3, intent3, PendingIntent.FLAG_UPDATE_CURRENT);
        view.setOnClickPendingIntent(R.id.ibSiguiente, pendingIntent3);

Esta otra notificación se emplea al momento que el usuario da clic en la notificación (en cualquier parte y no en sus botones).

        Intent intentNoti = new Intent(this, ListActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendIntentNoti = PendingIntent.getActivity(this, 0,
                intentNoti, PendingIntent.FLAG_UPDATE_CURRENT);

Cómo puedes darte cuenta, nos interesa actualizar el estatus de un servicio, que para efectos de esta entrada no importa su implementación.

Ahora podemos crear nuestra notificación; primero El administrador de la notificación (NotificationManager) que como su nombre indica mediante una instancia de esta clase podemos lanzar la notificación con el NotificationCompat.Builde podemos establecer las propiedades de la notificación; por ejemplo indicamos el título, subtítulo el icono y el PendingIntent cuya acción será ejercida al momento de que el usuario realice un clic sobre la notificación:

        NotificationManager nManager;
        NotificationCompat.Builder nBuilder;
        RemoteViews remoteView;


        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, ListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);


        nBuilder = new NotificationCompat.Builder(this)
                .setContentTitle(getString(R.string.app_name))
                .setTicker(getString(R.string.app_name))
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(contentIntent)
                .setOngoing(false)
                .setAutoCancel(false);

Ahora falta especificar cual es la vista en cuestión, esto lo hacemos mediante un RemoteViews:

        remoteView = new RemoteViews(getPackageName(), R.layout.notification_layout);
        remoteView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
        remoteView.setTextViewText(R.id.title, "Título");
        remoteView.setTextViewText(R.id.text,"Nombre");

Como podemos ver en el código anterior, accedemos a cada una de sus componentes y establecemos un valor que para efectos de este tutorial son fijos.

En nuestro caso la vista tiene el siguiente contenido:

<?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="wrap_content"
    android:background="#333333"
    android:orientation="vertical"
    android:weightSum="1">


    <LinearLayout
        android:id="@+id/right"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">


        <ImageView
            android:id="@+id/imagenotileft"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:background="@mipmap/ic_launcher" />


        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:orientation="vertical">


            <TextView
                android:id="@+id/title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:layout_marginTop="9dp"
                android:textColor="#FFFFFF"
                android:textSize="16sp"
                android:textStyle="bold" />


            <TextView
                android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/title"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:textColor="#EEEEEE"
                android:textSize="14sp" />
        </LinearLayout>


        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="horizontal">


            <ImageButton
                android:id="@+id/ibAtras"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_margin="0dp"
                android:background="@null"
                android:gravity="center_horizontal|center_vertical"
                android:padding="0dp"
                android:src="@drawable/ic_action_av_skip_previous" />


            <ImageButton
                android:id="@+id/ibAccion"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_margin="0dp"
                android:background="@null"
                android:gravity="center_horizontal|center_vertical"
                android:padding="0dp"
                android:src="@drawable/ic_action_ic_play_pause" />


            <ImageButton
                android:id="@+id/ibSiguiente"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_margin="0dp"
                android:background="@null"
                android:gravity="center_horizontal|center_vertical"
                android:padding="0dp"
                android:src="@drawable/ic_action_av_skip_next" />


            <Button
                android:id="@+id/ibQuitar"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_margin="0dp"
                android:background="@null"
                android:gravity="center_horizontal|center_vertical"
                android:padding="0dp"
                android:text="X"
                android:textColor="#444444"
                android:textSize="16sp" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Finalmente establecemos la vista anterior y lanzamos la notificación:

        setListeners(remoteView);
        nBuilder.setContent(remoteView);


        nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        nManager.notify(2, nBuilder.build());

Publicidad

Give me for a beer!

Algunos recursos que te pueden interesar

Creando increibles Drawer en Android con MaterialDrawer

Creando increibles Drawer en Android con MaterialDrawer

Paleta de colores para el Material Design

Paleta de colores para el Material Design

Librería oficial de PayPal para Android

Librería oficial de PayPal  para Android

Algunos artículos que te pueden interesar

Cómo ejecutar múltiples emuladores en Android Studio en un mismo proyecto

Cómo ejecutar múltiples emuladores en Android Studio en un mismo proyecto

Se explica como emplear múltiples emuladores en Android Studio en un mismo proyecto.

Andrés Cruz 24-10-2016

Llamadas asíncronas dentro y fuera del ámbito una Actividad en Android

Llamadas asíncronas dentro y fuera del ámbito una Actividad en Android

En esta entrada explicaremos como realizar llamadas asíncronas en el ámbito y fuera de una Actividad en Android.

Andrés Cruz 06-07-2015

Lo nuevo del Material Design: Los RecyclerView

Lo nuevo del Material Design: Los RecyclerView

Los RecyclerView al igual que los GridView y ListView, permite crear listados de ítems ya sea a través de listas o celdas y son una versión más flexible, potente y actualizada que los GridView ListView.

Andrés Cruz 07-10-2015