web-dev-qa-db-fra.com

Cliquer sur la notification n'ouvre pas l'activité mentionnée

J'essaie d'ouvrir un Activity lorsque la notification est cliquée et ci-dessous est mon code.

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

manifeste 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>

Chaque fois que je reçois une notification de la FCM, j'appelle cette notification. NotificationActivity ne s'ouvre pas chaque fois que je clique sur la notification, plutôt que l'application s'ouvre (splash screen->starting activity de mon flux d'application habituel). Chaque fois que je reçois une notification alors que l'application est déjà ouverte, le NotificationActivity s'ouvre, mais pas lorsque l'application n'est pas déjà ouverte. Quelqu'un pourrait-il m'aider à résoudre ce problème?

Note: Veuillez réitérer que NotificationActivity.class ne s'ouvre pas lorsque vous cliquez sur une notification lorsque l'application n'est pas déjà ouverte.

24
rick

Selon FCM Documentation, pour recevoir et gérer les messages,

Si vous souhaitez recevoir des notifications lorsque votre application est au premier plan, vous devez ajouter une logique de gestion des messages.

Pour recevoir des messages, utilisez un service qui étend FirebaseMessagingService. Votre service doit remplacer le rappel onMessageReceived, qui est fourni pour la plupart des types de messages, avec les exceptions suivantes:

1). Notifications délivrées lorsque votre application est en arrière-plan. Dans ce cas, la notification est envoyée dans la barre d'état système de l'appareil. Un utilisateur tapant sur une notification ouvre le lanceur d'applications par défaut.

2). Messages avec notification et données utiles, en arrière-plan et au premier plan. Dans ce cas, la notification est envoyée dans la barre d'état système de l'appareil et la charge utile des données est livrée dans les extras de l'intention de votre activité de lancement.

enter image description here

Donc, fondamentalement, nous avons deux types de charges utiles

1). Charge utile de notification

2). Charge utile des données

3). Les deux (un type supplémentaire que nous pouvons considérer).

Voyons maintenant un par un ces charges utiles. Avant cela, vous devez comprendre comment envoyer ces charges utiles à votre application. Tout ce que vous avez à faire est d'utiliser n'importe quel outil capable d'exécuter HTTP POST Request. Dans mon cas, j'utilise l'outil Postman , un Google Chrome Plugin.

Avant de créer un HTTP Post Request Pour FCM, vous devez considérer trois choses:

1). URL de demande de publication HTTP: https://fcm.googleapis.com/fcm/send

2). En-têtes de demande:

je). Type de contenu: application/json

ii). Autorisation: clé = YOUR_SERVER_KEY

Ci-dessous est la capture d'écran de la même chose pour montrer à quoi cela ressemble.

enter image description here

3). Corps: En cela, nous allons avoir JSON pour Notification et Data Payloads.

  • Donc, en commençant par Charge utile de notification , la plus simple de toutes. Dans ce cas, onMessageReceived() est appelée uniquement lorsque l'application est dans Foreground, pour tous les autres cas, c'est un System Tray Notification, Qui ouvre le Launcher Activity Lorsque cliqué. Ceci est utile lorsque vous ne voulez pas contrôler Notifications par vos propres moyens et pas beaucoup de données à traiter lorsque Notification arrive. Vous pouvez même contrôler le son, l'icône et l'action de clic (uniquement lorsque l'application est dans Foreground) sans écrire de code dans votre onMessageReceived(). Un exemple d'un corps de ces HTTP POST Request Est joint dans la capture d'écran ci-dessous.

enter image description here

Pour ouvrir le Activity souhaité lors de l'envoi du paramètre click_action, vous devez utiliser le code ci-dessous dans votre onMessageReceived().

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

et ci-dessous est votre méthode 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);
}

REMARQUE: Cette touche click_action Ne fonctionnera que lorsque l'application est au premier plan, pour tous les autres cas lorsque l'application est en arrière-plan et fermée, elle ne fonctionne pas. Il n'ouvre même pas l'activité du lanceur, en cas d'arrière-plan et de fermeture, si ce paramètre est spécifié.

  • Vient maintenant la charge utile des données . Ceci est similaire à celui que nous avons dans GCM. Ceci est très important si nous voulons gérer tous les trucs Notification par nous-mêmes comme nous le faisions tous dans le cas de GCM. Un exemple d'un corps de ces HTTP POST Request Est illustré ci-dessous.

enter image description here

Donc dans ce cas, onMessageReceived() est appelée à chaque fois et cela fonctionnera de la même manière que celle de GCM, si utile pour nous tous. Vous devez OverrideonMessageReceived() comme indiqué ci-dessous.

@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());
}
  • Enfin et surtout, nous pouvons envoyer à la fois Notification et Data Payloads. Dans ce cas, onMessageReceived() est appelée lorsque l'application est dans Foreground. Pour l'arrière-plan et l'état fermé, Notification vient dans la barre d'état système similaire à Notification Payload Mais la seule différence est que nous pouvons avoir data extras Ainsi que nous pouvons utiliser pour rediriger l'utilisateur vers un Activity souhaité, lorsque vous cliquez sur un Notification. Voici un exemple de corps de ce HTTP POST Request. Un exemple de corps de HTTP POST Request Est illustré ci-dessous.

enter image description here

Lorsque vous cliquez sur un Notification dans la barre d'état système, il ouvrira le Launcher Activity Et vous devez OverrideonCreate() de votre Launcher Activity Pour récupérez le data extras et redirigez l'utilisateur vers le Activity souhaité. Ci-dessous le code, vous devez écrire dans onCreate() de votre Activity pour rediriger l'utilisateur vers le Activity souhaité.

@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
}

Un autre cas de ce type est lorsque votre Launcher Activity Est défini comme launchMode="true" Dans le manifest et lorsque le Notification arrive, votre Launcher Activity est dans le Foreground. Ainsi, lorsque vous cliquez sur la notification, vous devez Override la méthode onNewIntent() dans votre Launcher Activity Pour ouvrir le Activity souhaité. Voici l'exemple de code pour le même.

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

Donc, en bref, je dirais que c'est bien d'aller avec le type Data Payload car il offre plus de flexibilité et de contrôle sur les Notification et plus important encore, car nous sommes tous habitués à GCM, donc ce type est ce que nous aimerions tous préférer.

Remarque: Certains appareils rencontrent des problèmes pour recevoir des notifications en arrière-plan, car j'ai trouvé des requêtes par-dessus ici. De plus, à l'époque, j'examinais ces cas, mon téléphone ASUS ne recevait aucune notification en arrière-plan pour l'un des types mentionnés ci-dessus. Vous ne savez donc pas quel est le problème avec ces appareils.

25
Mukesh Rana

Vous devez utiliser FLAG_UPDATE_CURRENT dans pendingIntent.

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

et passez également le même identifiant à notificationManager

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

Si vous lisez les documents Firebase en détail, il existe deux types de charges utiles

  • Charge utile de données
  • Charge utile de notification

La charge utile des données déclenche le rappel onMessageReceived () lorsque l'application est à la fois au premier plan et à l'arrière-plan. Ce n'est pas le cas avec la charge utile de notification, qui déclenche le rappel uniquement dans l'état de premier plan. Donc, si vous utilisez la charge utile de données, ce problème devrait être résolu.

0
Yash Ladia

Vérifiez ce code et faites-le moi savoir.

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

J'utilise ceci dans mon 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());
}
0
Shohan Ahmed Sijan

C'est le comportement intentionnel. Si votre application est en arrière-plan, la notification est créée par le système Android qui n'a pas votre action Intendant en attente. Donc, cela ne fonctionne pas. Dans le cas de premier plan, cela fonctionne car la notification est créée par votre code.

Veuillez vérifier la doc dans le lien ci-dessous. https://firebase.google.com/docs/notifications/Android/console-device#receive_and_handle_messages

0
rafa

Définissez votre intention en attente comme ci-dessous

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

ajoutez-le à votre notification en utilisant

.setContentIntent(pendingIntent);
0
Vijai

Vous pouvez spécifier n'importe quel Activity comme récepteur pour les notifications Push:

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

Ce filtre d'intention pour l'activité spécifie quelle activité sera lancée en réponse à la notification Push (PACKAGE_NAME est votre Android)

Vous pouvez donc ajouter ce filtre d'intention dans votre Activity que vous souhaitez ouvrir en cliquant sur Notification push.

0
Adheesh

Désolé de ne pas ajouter de commentaire car je suis un nouveau venu.

Vous pouvez simplement faire les deux choses suivantes pour une enquête plus approfondie:

  1. Une fois la notification créée, utilisez la commande Shell "adb Shell dumpsys activity i [votre nom de package]" pour voir votre notification en détail, pour confirmer qu'elle correspond vraiment à ce que vous voulez. N'oubliez pas de remplacer "[votre nom de package]" par votre propre nom de package;

  2. Suivi du journal des événements pendant que vous le reproduisez à l'aide de "adb logcat -v threadtime -b events".

Publiez les deux et nous pourrions obtenir quelque chose d'utile sur ce qui ne va pas sous le capot.

0
huangjh