notificaciones hacer alertas java android push-notification firebase-cloud-messaging firebase-notifications

java - alertas - Al hacer clic en la notificación no se abre la actividad mencionada



hacer notificaciones en java (9)

Esa es la conducta intencionada. Si su aplicación está en segundo plano, el sistema de Android creará una notificación que no tiene su acción de Acción pendiente. Por lo tanto, no funciona. En el caso de primer plano funciona porque la notificación es creada por su código.

Por favor, consulte el documento en el siguiente enlace. https://firebase.google.com/docs/notifications/android/console-device#receive_and_handle_messages

Estoy intentando abrir una Activity cuando se hace clic en la notificación y debajo está mi código.

Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class); intent.putExtra("msgBody",messageBody); intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_SINGLE_TOP |Intent.FLAG_ACTIVITY_CLEAR_TOP); //Tried with many options here PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent, PendingIntent.FLAG_CANCEL_CURRENT); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.otp_icon) .setContentTitle("Push MSG") .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build());

Manifiesto de Android:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.com.pushapp"> <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="21" /> <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_LOGS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application android:name=".AndroidPushApp" android:allowBackup="true" android:icon="@drawable/ic_launcher"> <activity android:name=".PushSplashScreen" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MainApplicationScreen" android:screenOrientation="portrait" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> </activity> <activity android:name=".StartActivity" android:launchMode="singleTask" android:screenOrientation="portrait" android:uiOptions="splitActionBarWhenNarrow" android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter> </activity> <service android:name=".MyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:name=".MyFirebaseInstanceIDService"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service> <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" /> <activity android:name=".NotificationActivity" android:exported="true" android:label="@string/title_activity"> <intent-filter> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>

Cada vez que recibo una notificación de FCM, llamo a esta notificación. NotificationActivity no se abre cuando hago clic en la notificación, en lugar de que la aplicación se abra ( splash screen->starting activity de splash screen->starting activity de mi flujo de aplicaciones habitual). Cada vez que recibo una notificación cuando la aplicación ya está abierta, NotificationActivity se abre, pero no cuando la aplicación aún no está abierta. ¿Podría alguien ayudarme por favor a resolver esto?

Nota: Reitero que NotificationActivity.class no se abre cuando se hace clic en la notificación cuando la aplicación aún no está abierta.


Establecer su intención pendiente como a continuación

Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class); intent.putExtra("msgBody",messageBody); intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

agregarlo a su notificación usando

.setContentIntent(pendingIntent);


Lo siento por no agregar un comentario ya que soy un recién llegado.

Puedes hacer las siguientes dos cosas para seguir investigando:

  1. Una vez creada la notificación, use el comando de shell "adb shell dumpsys activity i [nombre de su paquete]" para ver su notificación en detalle, para confirmar que realmente es lo que desea. Recuerde reemplazar "[nombre de su paquete]" con su propio nombre de paquete;

  2. Rastreando el registro de eventos durante el tiempo que está reproduciendo esto usando "adb logcat -v threadtime -b events".

Publique ambos y podríamos obtener algo útil sobre lo que está mal debajo del capó.


Puede especificar cualquier Activity para ser receptor de notificaciones push:

<intent-filter> <action android:name="PACKAGE_NAME.MESSAGE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>

Este filtro de intención para la actividad especifica qué actividad se iniciará en respuesta a la notificación de inserción ( PACKAGE_NAME es su paquete de aplicaciones de Android)

Por lo tanto, puede agregar este filtro de intención en su Activity que desea abrir con el clic de la notificación Push.


Revisa este código y házmelo saber.

Intent intent = new Intent(this, LoginActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);


Según la documentación de FCM , para recibir y manejar mensajes,

Si desea recibir notificaciones cuando su aplicación está en primer plano, necesita agregar alguna lógica de manejo de mensajes.

Para recibir mensajes, use un servicio que extienda FirebaseMessagingService. Su servicio debe anular la devolución de llamada onMessageReceived, que se proporciona para la mayoría de los tipos de mensajes, con las siguientes excepciones:

1). Notificaciones entregadas cuando su aplicación está en segundo plano. En este caso, la notificación se entrega a la bandeja del sistema del dispositivo. Un toque de usuario en una notificación abre el iniciador de aplicaciones de forma predeterminada.

2). Mensajes con notificación y carga útil de datos, tanto en segundo plano como en primer plano. En este caso, la notificación se entrega a la bandeja del sistema del dispositivo, y la carga útil de datos se entrega en los extras de la intención de su Actividad del iniciador.

Así que, básicamente, tenemos dos tipos de cargas útiles

1). Carga útil de notificación

2). Carga útil de datos

3). Ambos (un tipo adicional que podemos considerar).

Ahora vamos a discutir una por una estas cargas útiles. Antes de eso, debe comprender cómo puede enviar estas cargas útiles a su aplicación. Todo lo que tiene que hacer es utilizar cualquier herramienta que pueda realizar una HTTP POST Request . En mi caso, estoy usando la herramienta Postman , un complemento de Google Chrome.

Antes de realizar una HTTP Post Request para FCM , debe considerar tres cosas:

1). URL de solicitud de publicación HTTP: https://fcm.googleapis.com/fcm/send

2). Encabezados de solicitud:

yo). Tipo de contenido: aplicación / json

ii). Autorización: clave = YOUR_SERVER_KEY

A continuación se muestra la captura de pantalla de la misma para mostrar cómo se ve.

3). Cuerpo: En esto vamos a tener JSON para Notification y Data Payloads .

  • Así que comenzando con Notification Payload , la más sencilla de todas. En este caso, se llama a onMessageReceived() solo cuando la aplicación está en Foreground . Para todos los demás casos, se trata de una System Tray Notification , que abre la Launcher Activity del Launcher Activity cuando se hace clic. Esto es útil cuando no desea controlar las Notifications por su cuenta y no hay mucha información para tratar cuando llega la Notification . Incluso puede controlar el sonido, el ícono y la acción de hacer clic (solo cuando la aplicación está en Foreground ) sin escribir ningún código en su onMessageReceived() . Un ejemplo de un cuerpo de dicha HTTP POST Request se adjunta en la siguiente captura de pantalla.

Para abrir la Activity deseada al enviar el parámetro click_action, tiene que usar el siguiente código en su onMessageReceived() .

@Override public void onMessageReceived(RemoteMessage remoteMessage) { if (null != remoteMessage.getNotification().getClickAction()) { startActivity(remoteMessage.getNotification().getClickAction(), null, this); } }

y debajo está tu método startActivity() :

public void startActivity(String className, Bundle extras, Context context) { Class cls = null; try { cls = Class.forName(className); } catch (ClassNotFoundException e) { //means you made a wrong input in firebase console } Intent intent = new Intent(context, cls); if (null != extras) { intent.putExtras(extras); } intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); }

NOTA: esta tecla de click_action solo funcionará cuando la aplicación esté en primer plano, para todos los demás casos, cuando la aplicación esté en segundo plano y cerrada, no funcionará. Ni siquiera abre la Actividad del iniciador, en caso de Fondo y Cerrado, si se especifica este parámetro.

  • Ahora viene la carga útil de datos . Esto es similar al que tenemos en GCM . Esto es muy importante si queremos manejar todo lo relacionado con la Notification por nosotros mismos, igual que todos estábamos haciendo en el caso de GCM . A continuación se muestra un ejemplo de un cuerpo de dicha HTTP POST Request .

Entonces, en este caso, onMessageReceived() se llama cada vez y esto funcionará de la misma manera que GCM , que es muy útil para todos nosotros. onMessageReceived() como se muestra a continuación.

@Override public void onMessageReceived(RemoteMessage remoteMessage) { Map<String, String> data = remoteMessage.getData(); if (null != data && 0 < data.size()) { if (data.containsKey("custom_key_1")) { sendNotification(data.get("custom_key_1")); } } } private void sendNotification(String messageBody) { Intent intent = new Intent(this, DesiredActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_stat_ic_notification) .setContentTitle("FCM Message") .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()); }

  • Por último, pero no menos importante, también podemos enviar Notification y Data Payloads . En este caso, se llama a onMessageReceived() cuando la aplicación está en Foreground . Para el estado de fondo y cerrado, la Notification viene en la bandeja del sistema similar a la Notification Payload pero la única diferencia es que también podemos tener data extras que podemos usar para redirigir al usuario a una Activity deseada, cuando se hace clic en una Notification . A continuación se muestra el ejemplo de un cuerpo de dicha HTTP POST Request A continuación se muestra un ejemplo de un cuerpo de dicha HTTP POST Request .

Al hacer clic en una Notification en la bandeja del sistema, se abrirá la Launcher Activity onCreate() y deberá Override onCreate() de su Launcher Activity del onCreate() para obtener los data extras y redirigir al usuario a la Activity deseada. A continuación se muestra el código, debe escribir en onCreate() de su Activity para redirigir al usuario a la Activity deseada.

@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1") .equals("custom_value_1")){ startActivity(new Intent(this, DesiredActivity.class)); finish(); return; } // other operations }

Otro caso para este tipo es cuando la Launcher Activity launchMode="true" se define como launchMode="true" en el manifest y cuando llega la Notification , la Launcher Activity está en Foreground . Entonces, cuando hace clic en la Notificación, tiene que Override el método onNewIntent() en su Launcher Activity onNewIntent() para abrir la Activity deseada. A continuación se muestra el código de ejemplo para el mismo.

@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1") .equals("custom_value_1")) { startActivity(new Intent(this, DesiredActivity.class)); finish(); } }

En resumen, diría que es bueno ir con el tipo de carga de datos, ya que proporciona más flexibilidad y control sobre la Notification y, lo que es más importante, ya que todos estamos acostumbrados a GCM , por lo que este tipo es el que todos preferiríamos.

Nota: Algunos dispositivos tienen problemas para recibir notificaciones en segundo plano porque encontré algunas consultas sobre el mismo aquí. Además, en ese momento, estaba investigando estos casos, mi teléfono ASUS no estaba recibiendo notificaciones en segundo plano para ninguno de los tipos mencionados anteriormente. Así que no estoy seguro de cuál es el problema con estos dispositivos.


Si lees los documentos de Firebase en detalle, hay dos tipos de cargas útiles

  • Carga útil de datos
  • Carga útil de notificación

La carga útil de datos activa la devolución de llamada onMessageReceived () cuando la aplicación está en primer plano y en segundo plano. Este no es el caso de la carga útil de notificación, que activa la devolución de llamada solo en el estado de primer plano. Por lo tanto, si utiliza la carga útil de datos, este problema debería resolverse.


Tienes que usar FLAG_UPDATE_CURRENT en pendingIntent.

PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationId /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);

y también pasar el mismo ID a notificationManager

notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());


Yo uso esto en mi FirebaseMessagingService:

/** * Create and show a simple notification containing the received FCM message. * * @param messageBody FCM message body received. */ private void sendNotification(String title, String messageBody, String data) { Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT); Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(getApplicationContext()) .setSmallIcon(R.mipmap.ic_launcher) .setContentTitle(title) .setContentText(messageBody) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(this.NOTIFICATION_SERVICE); notificationManager.notify(id++ /* ID of notification */, notificationBuilder.build()); }