Cómo crear una notificación en Android Studio | Jetpack Compose

Video thumbnail

Las notificaciones son esos componentes que aparecen en la parte superior cuando deslizamos la barra de tareas. Como has podido notar al usar Android, es un elemento extremadamente personalizable y potente. Cualquier aplicación moderna las utiliza de formas distintas, lo que demuestra el alto nivel de personalización que podemos alcanzar.

En esta guía veremos dos ejemplos:

  1. Una notificación simple.
  2. Una notificación que nos redirige a una pantalla específica de nuestra app.

En esta entrada veremos cómo crear una notificación personalizada en Android. Exploraremos dos enfoques: el método tradicional (Legacy) basado en layouts XML y el enfoque moderno utilizando Jetpack Compose para diseñar la interfaz de usuario de la notificación.

Antes vimos como mostrar una pagina web con WebView en Android Studio | Jetpack Compose

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

A que emplearemos una vista desarrollada desde cero para tal fin; incluso emplearemos una serie de botones los cuales pueden ejercer sus acciones sobre la actividad que crea dicha notificación, servicios o Broadcast que definieramos.

Creando Notificaciones con Jetpack Compose (El Nuevo Enfoque)

Con la llegada de Jetpack Compose, la forma de construir interfaces de usuario en Android ha cambiado radicalmente. Naturalmente, uno querría usar Compose para el diseño de las notificaciones personalizadas. Sin embargo, aquí es donde las cosas se complican.

La Limitación: RemoteViews

El sistema de notificaciones de Android no ha sido rediseñado (aún) para soportar Composables de forma nativa. Las notificaciones personalizadas dependen obligatoriamente de un objeto RemoteViews, el cual está diseñado para inflar layouts definidos en XML. No puede procesar una función Composable directamente.

El Workaround: Renderizar a Bitmap

El enfoque actual para usar Compose en una notificación es una solución alternativa (workaround):

  1. Crear la UI con Compose: Diseñas la apariencia de tu notificación en una función @Composable aislada.
  2. Renderizar a un Bitmap: En tu código, inflas este Composable fuera de la pantalla y capturas su representación gráfica como un objeto Bitmap. Este es un proceso complejo que implica crear una vista temporal para alojar el Composable.
  3. Usar el Bitmap en un XML: Creas un layout XML simple para la RemoteViews que contenga únicamente un ImageView.
  4. Construir la Notificación: Asignas el Bitmap generado desde tu Composable al ImageView del RemoteViews y construyes la notificación como de costumbre.

️ Configuración inicial y Actividades

Antes de empezar, lo primero es habilitar los permisos de tipo POST_NOTIFICATIONS en el archivo AndroidManifest.

Para la segunda demostración, necesitaremos una actividad secundaria. En mi caso, he creado una actividad llamada Menu. Recuerda que el código fuente está en el repositorio; lo que hice fue duplicar la actividad principal, cambiarle el nombre a la clase y al archivo, y registrarla en el Manifest al mismo nivel que la actividad principal para que el sistema pueda reconocerla.

app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <application
        ***
        </activity>
        <activity
            android:name=".MenuActivity"
            android:exported="false"> </activity>
    </application>

</manifest>

Creación del Canal de Notificación (Notification Channel)

Desde Android 8.0 (API 26), es obligatorio crear un canal para poder enviar notificaciones. El propósito es mejorar la experiencia del usuario y evitar el "bombardeo" publicitario.

Ejemplo: Una aplicación bancaria puede tener un canal de Seguridad (indispensable para avisar sobre consumos) y otro de Promociones (publicidad). Si el usuario se cansa de la publicidad, puede desactivar ese canal específico desde los ajustes del sistema sin dejar de recibir las alertas de seguridad.

Para crear el canal, seguimos estos pasos:

  • Verificar la versión: Solo es necesario para Android 8 o superior.
  • Configurar el canal: Asignamos un ID, un nombre y una descripción que el usuario verá en los ajustes.
  • Nivel de importancia: Definimos la prioridad. Esto determina si la notificación emitirá sonido, vibrará o aparecerá de forma silenciosa. Pensando en el usuario, si no es urgente, no debemos ser intrusivos.

Una vez creado el canal, el sistema operativo permitirá mostrar las notificaciones que enviemos a través de él.

app/src/main/java/com/example/myproyectandroid/MainActivity.kt

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        createNotificationChannel(context = this);

        enableEdgeToEdge()
        ***
    }
    
    private fun createNotificationChannel(context: Context) {
        // Solo es necesario para API 26+ (Android 8.0)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Notificaciones de Mi App"
            val descriptionText = "Este canal se usa para alertas generales"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            // EL ID DEBE SER EL MISMO QUE USAS EN EL BUILDER ("CHANNEL_ID_EJEMPLO")
            val channel = NotificationChannel("CHANNEL_ID_EJEMPLO", name, importance).apply {
                description = descriptionText
            }

            // Registrar el canal con el sistema
            val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
} 

Configurar el canal

Ese error de Logcat es el más común con notificaciones en Android moderno. El sistema te está diciendo claramente: "Intentaste enviar una notificación a una caja llamada 'CHANNEL_ID_EJEMPLO', pero esa caja no existe en mi sistema".

En Android 8.0 (Oreo) y superiores, no basta con definir el ID en la notificación; tienes que registrar el canal en el sistema operativo antes de enviar cualquier mensaje. Si no lo haces, Android bloquea la notificación por seguridad.

No Channel found for pkg=com.example.myproyectandroid, channelId=CHANNEL_ID_EJEMPLO, id=101, tag=null, opPkg=com.example.myproyectandroid, callingUid=10217, userId=0, incomingUserId=0, notificationUid=10217, notification=Notification(channel=CHANNEL_ID_EJEMPLO shortcut=null contentView=null vibrate=null sound=null defaults=0 flags=AUTO_CANCEL color=0x00000000 vis=PRIVATE)

️ Gestión de Permisos y Envío Simple

En versiones recientes (Android 13+), el sistema muestra un diálogo preguntando si el usuario permite que la aplicación envíe notificaciones. Debemos manejar tres escenarios:

  • Permiso concedido: Simplemente lanzamos la notificación.
  • Permiso denegado: Debemos solicitarlo mediante un launcher.
  • Versiones antiguas: El sistema las muestra por defecto.

app/src/main/java/com/example/myproyectandroid/MainActivity.kt

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        createNotificationChannel(context = this);

        enableEdgeToEdge()
        setContent {
            MyProyectAndroidTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Column(modifier = Modifier.padding(innerPadding)) {
                        Greeting(
                            name = "Android",
                            modifier = Modifier.padding(innerPadding)
                        )
                        NotificationButton()
                    }
                }
            }
        }
    }
}

@Composable
fun NotificationButton() {
    val context = LocalContext.current

    // 1. Configuramos el "pedidor" de permisos
    val permissionLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestPermission()
    ) { isGranted ->
        if (isGranted) {
            // El usuario dijo que sí, lanzamos la notificación
            showSimpleNotification(context)
        } else {
            // El usuario dijo que no, podrías mostrar un Toast informativo
        }
    }

    Button(onClick = {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            // 2. Antes de lanzar, comprobamos si ya lo tenemos
            val hasPermission = ContextCompat.checkSelfPermission(
                context, Manifest.permission.POST_NOTIFICATIONS
            ) == PackageManager.PERMISSION_GRANTED
            showSimpleNotification(context)

            if (hasPermission) {
                 showSimpleNotificationOpenActivity(context)
                //showSimpleNotification(context)
            } else {
                // 3. Si no, disparamos el diálogo del sistema
                permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
            }
        } else {
            showSimpleNotificationOpenActivity(context)
            //showSimpleNotification(context)
        }
    }) {
        Text("Notificar con seguridad")
    }

}

Primera Notificación simple

Utilizamos NotificationCompat.Builder para definir:

  • Icono y Título: Lo que el usuario verá primero.
  • Texto: El cuerpo del mensaje.
  • AutoCancel: Para que la notificación desaparezca al tocarla.
  • ID Único: Usamos un identificador (ej. 101) que nos permitirá actualizar la notificación más adelante si fuera necesario.

app/src/main/java/com/example/myproyectandroid/MainActivity.kt

fun showSimpleNotification(context: Context) {
    val builder = NotificationCompat.Builder(context, "CHANNEL_ID_EJEMPLO")
        .setSmallIcon(android.R.drawable.ic_dialog_info) // Icono obligatorio
        .setContentTitle("¡Hola!")
        .setContentText("Esta es una notificación desde Jetpack Compose")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setAutoCancel(true) // Se cierra al tocarla

    with(NotificationManagerCompat.from(context)) {
        // El ID 101 es único para esta notificación (puedes usarlo para actualizarla luego)
        try {
            with(NotificationManagerCompat.from(context)) {
                notify(101, builder.build())
            }
        } catch (e: SecurityException) {
            // Manejar el error: registrarlo o avisar al usuario
            Log.e("Notificación", "Error de seguridad: falta permiso", e)
        }
    }
}

Notificaciones con Navegación (PendingIntent)

El segundo ejemplo consiste en que, al hacer clic en la notificación, el usuario sea dirigido a la pantalla de Menu.

El uso de Intents y PendingIntent

Para esto usamos un Intent, que es el objeto que transporta los datos entre actividades.

Verás que usamos MenuActivity::class.java. Esto es porque, internamente, los Intents de Android todavía esperan referencias de tipo Java (bytecode) para gestionar la navegación entre clases.

Encapsulamos este Intent en un PendingIntent. Este objeto le da permiso al sistema operativo para ejecutar una acción en nombre de nuestra aplicación (abrir la actividad) incluso si nuestra app está cerrada. Finalmente, usamos .setContentIntent(pendingIntent) en nuestro constructor de la notificación y la lanzamos.

app/src/main/java/com/example/myproyectandroid/MainActivity.kt

fun showSimpleNotificationOpenActivity(context: Context) {
    // 1. EL DESTINO: Aquí es donde especificas MenuActivity
    val intent = Intent(context, MenuActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }

    // 2. EL PENDING INTENT: El "permiso" para que el sistema abra la actividad
    val pendingIntent = PendingIntent.getActivity(
        context,
        0,
        intent,
        PendingIntent.FLAG_IMMUTABLE // Obligatorio en Android moderno
    )

    // 3. CONSTRUIR LA NOTIFICACIÓN
    val builder = NotificationCompat.Builder(context, "CHANNEL_ID_EJEMPLO")
        .setSmallIcon(android.R.drawable.ic_dialog_info)
        .setContentTitle("Acceso al Menú")
        .setContentText("Haz clic aquí para ir a MenuActivity")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent) // <--- Vincular el click con el destino
        .setAutoCancel(true) // Se borra al tocarla

    // 4. LANZAR (Con chequeo de permiso para evitar errores)
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
        NotificationManagerCompat.from(context).notify(101, builder.build())
    }
}

Creando la notificación personalizada Forma Legacy con XML

Los intent en el paso de datos

El código de la vista está un poco más adelante en la entrada, 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 el propósito de cada componente del código presentado anteriormente:

  • El Bundle Es empleado generalmente para pasar datos entre componentes como actividades y fragments a través de números, textos o booleanos.
  • El Intent es 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>

Indica que la actividad existe actualmente (por defecto la 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).

Definiendo las acciones de la vista personalizada

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);

Lanzando la notificación personalizada

Ahora podemos crear nuestra notificación; primero el administrador de la notificación (NotificationManager) que como su nombre indica y mediante una instancia de esta clase podemos lanzar la notificación con el NotificationCompat.Builde podemos establecer las propiedades de la notificación y crear la notificación propiamente dicha; 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);

Como podemos apreciar, al momento de crear la notificación establecemos varios parámetros como el contenido (título), icono y el mismo Intent que definimos anteriormente.

Ahora falta especificar cual es la vista en cuestión (la que posee el diseño que creamos con los tres botones), 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>
Notificación Personalizada

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());

Replicar las notificaciones en Android

Hasta ahora hemos visto cómo crear una notificación con un layout personalizado y cómo interactuar con los elementos que definimos en este layout como Buttons o ImageView, etc; en esta segunda parte de esta entrada veremos cómo crear notificaciones que se puedan replicar; esta es una acción muy empleada en aplicaciones de mensajería como Hangout de Google o el mismo Whatsapp en Android.

Compatibilidad y la transición a AndroidX

Originalmente, para asegurar la compatibilidad hacia atrás, se utilizaban las Librerías de Soporte (Support Library). Este es el método que podríamos considerar "Legacy". Las clases como NotificationCompat.Builder provenían del paquete android.support.v4.app.

Actualmente, el ecosistema de desarrollo de Android ha evolucionado hacia AndroidX. Esta es la nueva forma estándar y recomendada. AndroidX reemplaza a las Support Libraries y ofrece un desarrollo más consistente y moderno. Para usarlo, se deben declarar las dependencias en el archivo build.gradle de la aplicación, lo que es análogo a cómo se usa Composer en proyectos de PHP/Laravel para gestionar paquetes.

Por ejemplo, para incluir la librería necesaria para las notificaciones, agregarías algo como esto a tu build.gradle:

dependencies {
    implementation "androidx.core:core-ktx:1.13.1"
}

Aunque este artículo mostrará ejemplos que usan la clase NotificationCompat.Builder, es crucial entender que ahora reside en el paquete androidx.core.app. Los conceptos son los mismos, pero la implementación y las dependencias han sido modernizadas. Se pueden emplear muchisimas opciones que tienen desde prioridad hasta estilos, pero siempre teniendo en cuenta que algunas funciones específicas requieren versiones de Android más recientes.

Creando el medio para el pase de datos entre componentes: PendingIntent

Lo primero que debemos hacer es crear un PendingIntent y asociar el Intent que es el medio empleado para pasar datos de un componente; estos componentes no solo pueden ser Actividades o Fragments, también pueden ser otros como Broadcast para realizar actualizaciones en segundo plano sin la necesidad de invocar a la actividad; aunque para esto debemos emplear Android N en adelante; para no extender demasiada esta entrada, nos iremos por el caso en que se invoca a la actividad.

El PendingIntent es el mecanismo existente que tenemos para pasar datos entre distintos componentes como actividades, broadcast o servicios que embebe dentro del mismo los datos que queremos pasar a estos componentes (en caso de que se desee pasar un dato):

RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
       .setLabel(replyLabel)
       .build();
Intent resultIntent = new Intent(this, MainActivity.class);
resultIntent.setAction(KEY_TEXT_REPLY);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent replyPendingIntent =
       stackBuilder.getPendingIntent(
               0,
               PendingIntent.FLAG_UPDATE_CURRENT
       );

El método setAction permite asociar el nombre del dato a pasar, que en este caso será el texto que el usuario suministre en el campo de réplica y con este nombre accedemos al texto que ingreso el usuario en el onCreate de nuestra actividad:

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   Intent intent = getIntent();
   if (KEY_TEXT_REPLY.equals(intent.getAction())) {
       Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
       if (remoteInput != NULL) {
           Log.i("REPLICA", "" + remoteInput.getCharSequence(KEY_TEXT_REPLY));
       }
   }
   replyNotification();
}

Con el método RemoteInput indicamos que crearemos un mecanismo para el pase de datos dentro del PendingIntent; además de asociamos el label o texto que va a aparecer en el campo de la réplica.

Creando la notificación replica

Asociamos el PendingIntent que creamos anteriormente:

NotificationCompat.Action action =
       new NotificationCompat.Action.Builder(R.mipmap.ic_launcher,
               "Replicar", replyPendingIntent)
               .addRemoteInput(remoteInput)
               .build();

Creando la notificación replica

Creamos la notificación estableciendo el contenido de la misma: icono representativo, título, contenido y la acción que configuramos en el bloque anterior:

NotificationCompat.Builder newMessageNotification =
       new NotificationCompat.Builder(MainActivity.this)
               .setSmallIcon(R.mipmap.ic_launcher)
               .setContentTitle("My notification")
               .setContentText("Hello World!")
               .addAction(action);

Finalmente lanzamos la notificación junto con las acción que configuramos en los pasos anteriores a través del método build():

NotificationManagerCompat notificationManager =
       NotificationManagerCompat.from(MainActivity.this);
notificationManager.notify(NOTIFICATION_ID, newMessageNotification.build());

El método completo queda como:

    public void replyNotification() {
        RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
                .setLabel(replyLabel)
                .build();
        Intent resultIntent = new Intent(this, MainActivity.class);
        resultIntent.setAction(KEY_TEXT_REPLY);
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent replyPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );
        NotificationCompat.Action action =
                new NotificationCompat.Action.Builder(R.mipmap.ic_launcher,
                        "Replicar", replyPendingIntent)
                        .addRemoteInput(remoteInput)
                        .build();
        NotificationCompat.Builder newMessageNotification =
                new NotificationCompat.Builder(MainActivity.this)
                        .setSmallIcon(R.mipmap.ic_launcher)
                        .setContentTitle("My notification")
                        .setContentText("Hello World!")
                        .addAction(action);
        NotificationManagerCompat notificationManager =
                NotificationManagerCompat.from(MainActivity.this);
        notificationManager.notify(NOTIFICATION_ID, newMessageNotification.build());
    }

Finalmente el resultado es el siguiente:

Notificación de Réplica en android

Siguiente paso, aprende a conectarte a APIs Rest en Android Studio.

Mostrar Notificaciones en Android, Aprende a configurar Notification Channels, gestionar permisos en Android 13+ y usar PendingIntent para navegación.

Acepto recibir anuncios de interes sobre este Blog.

Andrés Cruz

EN In english