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:
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;
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á enForeground
. Para todos los demás casos, se trata de unaSystem Tray Notification
, que abre laLauncher Activity
delLauncher Activity
cuando se hace clic. Esto es útil cuando no desea controlar lasNotifications
por su cuenta y no hay mucha información para tratar cuando llega laNotification
. Incluso puede controlar el sonido, el ícono y la acción de hacer clic (solo cuando la aplicación está enForeground
) sin escribir ningún código en suonMessageReceived()
. Un ejemplo de un cuerpo de dichaHTTP 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 laNotification
por nosotros mismos, igual que todos estábamos haciendo en el caso deGCM
. A continuación se muestra un ejemplo de un cuerpo de dichaHTTP 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
yData Payloads
. En este caso, se llama aonMessageReceived()
cuando la aplicación está enForeground
. Para el estado de fondo y cerrado, laNotification
viene en la bandeja del sistema similar a laNotification Payload
pero la única diferencia es que también podemos tenerdata extras
que podemos usar para redirigir al usuario a unaActivity
deseada, cuando se hace clic en unaNotification
. A continuación se muestra el ejemplo de un cuerpo de dichaHTTP POST Request
A continuación se muestra un ejemplo de un cuerpo de dichaHTTP 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());
}