Índice de contenido
- Creando Notificaciones con Jetpack Compose (El Nuevo Enfoque)
- La Limitación: RemoteViews
- El Workaround: Renderizar a Bitmap
- ️ Configuración inicial y Actividades
- Creación del Canal de Notificación (Notification Channel)
- Configurar el canal
- ️ Gestión de Permisos y Envío Simple
- Primera Notificación simple
- Notificaciones con Navegación (PendingIntent)
- Creando la notificación personalizada Forma Legacy con XML
- Los intent en el paso de datos
- Definiendo las acciones de la vista personalizada
- Lanzando la notificación personalizada
- Replicar las notificaciones en Android
- Compatibilidad y la transición a AndroidX
- Creando el medio para el pase de datos entre componentes: PendingIntent
- Creando la notificación replica
- Creando la notificación replica
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:
- Una notificación simple.
- 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):
- Crear la UI con Compose: Diseñas la apariencia de tu notificación en una función
@Composableaislada. - 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. - Usar el Bitmap en un XML: Creas un layout XML simple para la
RemoteViewsque contenga únicamente unImageView. - Construir la Notificación: Asignas el Bitmap generado desde tu Composable al
ImageViewdelRemoteViewsy 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
BundleEs empleado generalmente para pasar datos entre componentes como actividades y fragments a través de números, textos o booleanos. - El
Intentes 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
PendingIntentes un objeto que contiene a un intent; este objetoPendingIntentpermite alNotificationManagermandar 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>

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:

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