Firebase onMessageReceived non appelé lorsque l'application en arrière-plan

234

Je travaille avec Firebase et teste l'envoi de notifications à mon application depuis mon serveur pendant que l'application est en arrière-plan. La notification est envoyée avec succès, elle apparaît même sur le centre de notification de l'appareil, mais lorsque la notification apparaît ou même si je clique dessus, la méthode onMessageReceived dans mon FCMessagingService n'est jamais appelée.

Lorsque j'ai testé cela alors que mon application était au premier plan, la méthode onMessageReceived a été appelée et tout a bien fonctionné. Le problème se produit lorsque l'application s'exécute en arrière-plan.

Est-ce le comportement voulu ou existe-t-il un moyen de résoudre ce problème?

Voici mon FBMessagingService:

import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class FBMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("PVL", "MESSAGE RECEIVED!!");
        if (remoteMessage.getNotification().getBody() != null) {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getNotification().getBody());
        } else {
            Log.i("PVL", "RECEIVED MESSAGE: " + remoteMessage.getData().get("message"));
        }
    }
}
Cyogenos
la source
En plus du corps json, où est votre code onTokenRefresh ? Avez-vous terminé la configuration d'Android ?
Kato
4
Que voulez-vous dire par le corps json de la notification? De plus, mon code onTokenRefresh se trouve dans mon service FirebaseInstanceID.
Cyogenos
Pouvez-vous publier l'échantillon de charge utile que vous envoyez?
AL.
Vous pouvez également consulter ce fil stackoverflow.com/questions/39046270/…
Md. Sajedul Karim

Réponses:

145

Cela fonctionne comme prévu, les messages de notification sont envoyés à votre rappel onMessageReceived uniquement lorsque votre application est au premier plan. Si votre application est en arrière-plan ou fermée, un message de notification s'affiche dans le centre de notifications et toutes les données de ce message sont transmises à l'intention qui est lancée suite au tapement de l'utilisateur sur la notification.

Vous pouvez spécifier une action click_action pour indiquer l'intention à lancer lorsque la notification est exploitée par l'utilisateur. L'activité principale est utilisée si aucun click_action n'est spécifié.

Lorsque l'intention est lancée, vous pouvez utiliser le

getIntent().getExtras();

pour récupérer un ensemble qui inclurait toutes les données envoyées avec le message de notification.

Pour plus d'informations sur le message de notification, consultez la documentation .

Arthur Thompson
la source
6
Existe-t-il un moyen de définir le click_actionlorsque j'utilise la console de notification Firebase?
Nii Laryea
6
ok, mais qu'en est-il si l'application est supprimée (pas de premier plan ni d'arrière-plan)?
michalu
3
Mais comment désactiver la notification de rejet de l'utilisateur? Parce que si l'utilisateur le jette, cela signifie que toutes les données seront ignorées ...
Aleksey Timoshchenko
4
Correct! Ainsi, lors de l'envoi de messages de notification à Android, les données d'accompagnement doivent être des données qui améliorent l'expérience de notification. Il ne doit pas s'agir de données critiques pour l'application, utilisez des messages de données pour les données dont l'application a besoin même si l'utilisateur rejette la notification.
Arthur Thompson
3
Ce n'est pas tout à fait correct. Si le message ne contient que des données et non une charge utile de notification, le message sera TOUJOURS remis à onMessageReceive, si l'application est au premier plan ou non.
JacksOnF1re
126

Supprimeznotification complètement le champ de votre demande de serveur. Envoyez seulementdata et manipulez-le onMessageReceived()sinononMessageReceived() ne sera pas déclenchée lorsque l'application est en arrière-plan ou supprimée.

N'oubliez pas d'inclure "priority": "high" champ dans votre demande de notification. Selon la documentation: les messages de données sont envoyés avec une priorité normale, donc ils n'arriveront pas instantanément; cela pourrait aussi être le problème.

Voici ce que j'envoie depuis le serveur

{
  "data":{
    "id": 1,
    "missedRequests": 5
    "addAnyDataHere": 123
  },
  "to": "fhiT7evmZk8:APA91bFJq7Tkly4BtLRXdYvqHno2vHCRkzpJT8QZy0TlIGs......",
  "priority": "high"
}

Ainsi, vous pouvez recevoir vos données onMessageReceived(RemoteMessage message)comme ceci .... disons que je dois me

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }
Zohab Ali
la source
9
J'ai constaté que si j'envoie uniquement un message de données, l'application qui est effacée du gestionnaire de tâches ne pourra pas recevoir de notification. Est-ce un comportement prévu?
Prabhjot Singh,
2
C'était la solution pour moi de recevoir des messages en arrière-plan!
Ray Hulha
5
Dans Oreo, une fois l'application supprimée, onMessageReceived n'est pas appelé. J'ai juste une charge utile avec des données uniquement. avez-vous une mise à jour?
Samir Mangroliya
2
Fonctionne comme un charme!
ssk
3
Je vous aime beaucoup pour cette réponse: p
Ahmad Arslan
63

cette méthode handleIntent () a été dépréciée, donc la gestion d'une notification peut être effectuée comme suit:

  1. État de premier plan: le clic de la notification ira à l'activité de l'intention en attente que vous fournissez lors de la création d'une notification de manière programmatique, comme elle l'a généralement créé avec la charge utile de données de la notification.

  2. Contexte / État tué - Ici, le système lui-même crée une notification basée sur la charge utile de notification et en cliquant sur cette notification, vous accédez à l'activité de lancement de l'application où vous pouvez facilement récupérer les données d'intention dans n'importe laquelle de vos méthodes de cycle de vie.

manas.abrol
la source
Je vous remercie!!! J'ai perdu quelques jours sur ce problème et celui-ci m'a sauvé.
Igor Janković
vraiment la solution parfaite!
EduXavier
4
Je gère la logique d'affichage des notifications dans handleIntent (intention d'intention), cependant lorsque l'application est en arrière-plan, 2 notifications sont affichées, une que j'ai créée et une autre par défaut qui contient le message entier de la notification.
Joyson
5
Génial, mais je ne vois aucune utilité OnMessageReceiveddans ce cas!?
Alaa AbuZarifa
8
Je reçois com.google.firebase: Firebase-messaging: 11.6.2 et handleIntent est final maintenant.Check stackoverflow.com/questions/47308155/…
Ronak Poriya
31

Voici des concepts plus clairs sur le message Firebase. Je l'ai trouvé auprès de leur équipe d'assistance.

Firebase a trois types de messages :

Messages de notification : le message de notification fonctionne en arrière-plan ou au premier plan. Lorsque l'application est en arrière-plan, les messages de notification sont remis dans la barre d'état système. Si l'application est au premier plan, les messages sont gérés par onMessageReceived()oudidReceiveRemoteNotification rappels. Il s'agit essentiellement de ce que l'on appelle les messages d'affichage.

Messages de données : sur la plateforme Android, les messages de données peuvent fonctionner en arrière-plan et au premier plan. Le message de données sera géré par onMessageReceived (). Une note spécifique à la plate-forme serait ici: Sur Android, la charge utile des données peut être récupérée dans l'intention utilisée pour lancer votre activité. Pour élaborer, si vous en avez "click_action":"launch_Activity_1", vous pouvez récupérer cette intention getIntent()uniquement à partir de Activity_1.

Messages avec notification et données utiles : en arrière-plan, les applications reçoivent la charge utile de notification dans la barre de notification et ne gèrent la charge utile de données que lorsque l'utilisateur appuie sur la notification. Au premier plan, votre application reçoit un objet de message avec les deux charges utiles disponibles. Deuxièmement, le paramètre click_action est souvent utilisé dans la charge utile de notification et non dans la charge utile de données. S'il est utilisé dans les données utiles, ce paramètre sera traité comme une paire clé-valeur personnalisée et vous devrez donc implémenter une logique personnalisée pour qu'il fonctionne comme prévu.

En outre, je vous recommande d'utiliser la méthode onMessageReceived (voir Message de données) pour extraire le groupe de données. D'après votre logique, j'ai vérifié l'objet bundle et je n'ai pas trouvé le contenu de données attendu. Voici une référence à un cas similaire qui pourrait apporter plus de clarté.

Du côté serveur, la notification Firebase doit être au format suivant :

Le côté serveur doit envoyer un objet "notification" . Manque d'objet "notification" dans mon TargetActivitymessage qui n'a pas été utilisé getIntent().

Le format de message correct est donné ci-dessous:

{
 "data": {
  "body": "here is body",
  "title": "Title"
 },
"notification": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
 "to": "ffEseX6vwcM:APA91bF8m7wOF MY FCM ID 07j1aPUb"
}

Voici des concepts plus clairs sur le message Firebase. Je l'ai trouvé auprès de leur équipe d'assistance.

Pour plus d'informations visitez mon ce fil et ce fil

Md. Sajedul Karim
la source
3
il convient de mentionner que les "messages de données" ne seront pas reçus si l'appareil est en mode somnolence profonde (introduit dans Android 7.0). soyez prudent avec ceux-là!
Sameer J
30

J'ai eu le même problème. Il est plus facile d'utiliser le «message de données» au lieu de la «notification». Le message de données charge toujours la classe onMessageReceived.

Dans cette classe, vous pouvez faire votre propre notification avec le générateur de notifications.

Exemple:

 @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        sendNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
    }

    private void sendNotification(String messageTitle,String messageBody) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0 /* request code */, intent,PendingIntent.FLAG_UPDATE_CURRENT);

        long[] pattern = {500,500,500,500,500};

        Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_stat_name)
                .setContentTitle(messageTitle)
                .setContentText(messageBody)
                .setAutoCancel(true)
                .setVibrate(pattern)
                .setLights(Color.BLUE,1,1)
                .setSound(defaultSoundUri)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
    }
Koot
la source
7
Merci ..J'ai changé le code de mon serveur et j'utilise "données" au lieu de "notification" et maintenant ça fonctionne parfaitement,
Mahesh Kavathiya
5
@Koot ne fonctionne que si l'application est en premier plan et non en arrière-plan. pouvez-vous m'aider à déclencher cet événement dans les deux cas?
Anant Shah
@AnantShah à quoi ressemble votre POST sur le serveur Firebase?
Koot
3
Il y a en fait trois cas possibles ici. 1) Application en premier plan. 2) Application en arrière-plan. 3) L'application ne fonctionne pas. Comme vous le dites, un message «données» sera reçu dans les deux premiers cas, mais pas dans le troisième cas, lorsque l'application ne fonctionne pas. Pour répondre aux trois cas, vous devez définir le champ «notification» dans le message. (Aussi une bonne idée si vous voulez prendre en charge les clients iOS ainsi que Android)
Steve Moseley
1
Même dans l'application ne fonctionne pas, je reçois toujours un message du serveur sur la fonction onmessagereceived. Je suis d'accord avec vous qu'il est préférable d'utiliser la «notification» si vous souhaitez également prendre en charge iOS.
Koot
21

Selon la documentation de Firebase Cloud Messaging: si l'activité est au premier plan, onMessageReceived sera appelé. Si l'activité est en arrière-plan ou fermée, un message de notification s'affiche dans le centre de notification pour l'activité du lanceur d'applications. Vous pouvez appeler votre activité personnalisée au clic de la notification si votre application est en arrière-plan en appelant l'api du service de repos pour la messagerie Firebase comme:

URL- https://fcm.googleapis.com/fcm/send

Type de méthode - POST

Header- Content-Type:application/json
Authorization:key=your api key

Corps / Charge utile:

{ "notification": {
    "title": "Your Title",
    "text": "Your Text",
     "click_action": "OPEN_ACTIVITY_1" // should match to your intent filter
  },
    "data": {
    "keyname": "any value " //you can get this data as extras in your activity and this data is optional
    },
  "to" : "to_id(firebase refreshedToken)"
} 

Et avec cela dans votre application, vous pouvez ajouter le code ci-dessous dans votre activité pour être appelé:

<intent-filter>
                <action android:name="OPEN_ACTIVITY_1" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
Ankit Adlakha
la source
Où créer l'intention et la faire ouvrir une activité spécifique? Je sais que cela enregistre l'intention OPEN_ACTIVITY_1 dans le manifeste, mais où dois-je l'appeler?
Cyogenos
1
Vérifiez ceci: firebase.google.com/docs/cloud-messaging/…
Ankit Adlakha
Faut-il appeler une activité à partir de filtres d'intention? Ou le démarrer manuellement dans onMessageReceived?
CoolMind
14

Méthode onMessageReceived (RemoteMessage remoteMessage) appelée en fonction des cas suivants.

  • Réponse FCM avec notification et bloc de données :
{
  
"to": "device token list",
  "notification": {
    "body": "Body of Your Notification",
    "title": "Title of Your Notification"
  },
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}
  1. Application au premier plan:

onMessageReceived (RemoteMessage remoteMessage) appelé, affiche LargeIcon et BigPicture dans la barre de notification. Nous pouvons lire le contenu de la notification et du bloc de données

  1. Application en arrière-plan:

onMessageReceived (RemoteMessage remoteMessage) non appelé, la barre d'état système recevra le message et lira le corps et le titre du bloc de notification et affichera le message et le titre par défaut dans la barre de notification.

  • Réponse FCM Avec uniquement un bloc de données :

Dans ce cas, supprimer les blocs de notification de json

{
  
"to": "device token list",
  "data": {
    "body": "Body of Your Notification in Data",
    "title": "Title of Your Notification in Title",
    "key_1": "Value for key_1",
    "image_url": "www.abc.com/xyz.jpeg",
    "key_2": "Value for key_2"
  }
}

Solution pour appeler onMessageReceived ()

  1. Application au premier plan:

onMessageReceived (RemoteMessage remoteMessage) appelé, affiche LargeIcon et BigPicture dans la barre de notification. Nous pouvons lire le contenu de la notification et du bloc de données

  1. Application en arrière-plan:

onMessageReceived (RemoteMessage remoteMessage) appelé, la barre d'état système ne recevra pas le message car la clé de notification ne figure pas dans la réponse. Affiche LargeIcon et BigPicture dans la barre de notification

Code

 private void sendNotification(Bitmap bitmap,  String title, String 
    message, PendingIntent resultPendingIntent) {

    NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
    style.bigPicture(bitmap);

    Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

    NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    String NOTIFICATION_CHANNEL_ID = mContext.getString(R.string.default_notification_channel_id);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_HIGH);

        notificationManager.createNotificationChannel(notificationChannel);
    }
    Bitmap iconLarge = BitmapFactory.decodeResource(mContext.getResources(),
            R.drawable.mdmlogo);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext, NOTIFICATION_CHANNEL_ID)
            .setSmallIcon(R.drawable.mdmlogo)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(defaultSound)
            .setContentText(message)
            .setContentIntent(resultPendingIntent)
            .setStyle(style)
            .setLargeIcon(iconLarge)
            .setWhen(System.currentTimeMillis())
            .setPriority(Notification.PRIORITY_MAX)
            .setChannelId(NOTIFICATION_CHANNEL_ID);


    notificationManager.notify(1, notificationBuilder.build());


}

Lien de référence:

https://firebase.google.com/docs/cloud-messaging/android/receive

vishnuc156
la source
La partie la plus importante pour les personnes souffrant d'un problème d'arrière-plan est de supprimer la propriété "notification" du JSON envoyé par le serveur. cela résout le problème. Merci beaucoup.
Ramy M. Mousa
13

J'ai le même problème. Si l'application est au premier plan - elle déclenche mon service d'arrière-plan où je peux mettre à jour ma base de données en fonction du type de notification. Mais, l'application passe en arrière-plan - le service de notification par défaut veillera à afficher la notification à l'utilisateur.

Voici ma solution pour identifier l'application en arrière-plan et déclencher votre service en arrière-plan,

public class FirebaseBackgroundService extends WakefulBroadcastReceiver {

  private static final String TAG = "FirebaseService";

  @Override
  public void onReceive(Context context, Intent intent) {
    Log.d(TAG, "I'm in!!!");

    if (intent.getExtras() != null) {
      for (String key : intent.getExtras().keySet()) {
        Object value = intent.getExtras().get(key);
        Log.e("FirebaseDataReceiver", "Key: " + key + " Value: " + value);
        if(key.equalsIgnoreCase("gcm.notification.body") && value != null) {
          Bundle bundle = new Bundle();
          Intent backgroundIntent = new Intent(context, BackgroundSyncJobService.class);
          bundle.putString("push_message", value + "");
          backgroundIntent.putExtras(bundle);
          context.startService(backgroundIntent);
        }
      }
    }
  }
}

Dans le manifest.xml

<receiver android:exported="true" android:name=".FirebaseBackgroundService" android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>

Testé cette solution dans la dernière version d'Android 8.0. Merci

Nagendra Badiganti
la source
whare pour utiliser cette classe FirebaseBackgroundService ?? @Nagendra Badiganti
où utiliser ce code public class FirebaseBackgroundService étend WakefulBroadcastReceiver @Nagendra Badiganti
créez une classe de service dans votre package et enregistrez-vous dans votre manifest.xml. Assurez-vous que vous disposez du filtre pour vos notifications. Puisque le service se déclenche pour chaque notification GCM.
Nagendra Badiganti,
firebase.google.com/docs/cloud-messaging/android/… je suis ce lien, je dois ajouter cette classe pour recevoir une notification. simplement d' envoyer un message de premier message firebase .. il dit rempli mais ne reçoit pas la notification @Nagendra Badiganti
1
WakefulBroadcastReceiverest obsolète depuis le niveau API 26.1.0.
Minoru
12

Si l'application est en mode arrière-plan ou inactive (tuée) et que vous cliquez sur Notification , vous devez vérifier la charge utile dans LaunchScreen (dans mon cas, l'écran de lancement est MainActivity.java).

Donc, dans MainActivity.java sur onCreate, vérifiez les extras :

    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d("MainActivity: ", "Key: " + key + " Value: " + value);
        }
    }
Gent Berani
la source
Comment obtenir le titre, le corps et les données de la notification?
Md.Tarikul Islam
1
Merci, c'est la réponse. @ Md.Tarikul Islam utilisant onMessageReceived () comme mentionné dans cette question.
felixwcf
7

Remplacez la handleIntentméthode des FirebaseMessageServicetravaux pour moi.

ici le code en C # (Xamarin)

public override void HandleIntent(Intent intent)
{
    try
    {
        if (intent.Extras != null)
        {
            var builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            foreach (string key in intent.Extras.KeySet())
            {
                builder.AddData(key, intent.Extras.Get(key).ToString());
            }

            this.OnMessageReceived(builder.Build());
        }
        else
        {
            base.HandleIntent(intent);
        }
    }
    catch (Exception)
    {
        base.HandleIntent(intent);
    }
}

et c'est le code en Java

public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }

            onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}
t3h Exi
la source
handleIntent () est final
Ettore
@Ettore Comment puis-je appeler la fonction handleIntent?
Hiroto
La méthode est appelée lorsque vous recevez le message de Firebase, mais vous ne pouvez pas la remplacer car la méthode est déclarée finale. (Firebase 11.6.0)
Ettore
5

Par défaut, l' activité de lancement dans votre application sera lancée lorsque votre application est en arrière-plan et que vous cliquez sur la notification, si vous avez une partie de données avec votre notification, vous pouvez la gérer dans la même activité comme suit,

if(getIntent().getExtras()! = null){
  //do your stuff
}else{
  //do that you normally do
}
Uzair
la source
Si je navigue depuis mainActivity, comment fonctionnera pour revenir à une activité particulière?
Mac_Play
@Uzair getIntent (). GetExtras () devient toujours nul, avez-vous une autre solution? Lorsque l'application va au fond, la méthode onMessageReceived n'appelle pas
user2025187
3

Si l'application est en arrière-plan Fire-base par défaut, la notification de gestion Mais si nous voulons notre notification personnalisée, nous devons changer notre côté serveur, qui est responsable de l'envoi de nos données personnalisées (charge utile des données)

Supprimez complètement la charge utile de notification de votre demande de serveur. Envoyez uniquement des données et gérez-les dans onMessageReceived (), sinon votre onMessageReceived ne sera pas déclenché lorsque l'application est en arrière-plan ou supprimée.

maintenant, votre format de code côté serveur ressemble,

{
  "collapse_key": "CHAT_MESSAGE_CONTACT",
  "data": {
    "loc_key": "CHAT_MESSAGE_CONTACT",
    "loc_args": ["John Doe", "Contact Exchange"],
    "text": "John Doe shared a contact in the group Contact Exchange",
    "custom": {
      "chat_id": 241233,
      "msg_id": 123
    },
    "badge": 1,
    "sound": "sound1.mp3",
    "mute": true
  }
}

REMARQUE : voir cette ligne dans le code ci-dessus
"text": "John Doe a partagé un contact dans le groupe Contact Exchange" dans Data payload, vous devez utiliser le paramètre "text" au lieu des paramètres "body" ou "message" pour la description du message ou tout ce que vous voulez voulez utiliser du texte.

onMessageReceived ()

@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.e(TAG, "From: " + remoteMessage.getData().toString());

        if (remoteMessage == null)
            return;

        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
           /* Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());*/
            Log.e(TAG, "Data Payload: " + remoteMessage);

            try {

                Map<String, String> params = remoteMessage.getData();
                JSONObject json = new JSONObject(params);
                Log.e("JSON_OBJECT", json.toString());


                Log.e(TAG, "onMessageReceived: " + json.toString());

                handleDataMessage(json);
            } catch (Exception e) {
                Log.e(TAG, "Exception: " + e.getMessage());
            }
        }
    }
Hiren
la source
2

Appelez simplement ceci dans la méthode onCreate de votre MainActivity:

if (getIntent().getExtras() != null) {
           // Call your NotificationActivity here..
            Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
            startActivity(intent);
        }
Aman Shekhar
la source
Si je navigue depuis mainActivity, comment fonctionnera pour revenir à une activité particulière?
Mac_Play
2

selon la solution de t3h Exi, je voudrais publier le code propre ici. Il suffit de le mettre dans MyFirebaseMessagingService et tout fonctionne bien si l'application est en mode arrière-plan. Vous devez au moins compiler com.google.firebase: firebase-messaging: 10.2.1

 @Override
public void handleIntent(Intent intent)
{
    try
    {
        if (intent.getExtras() != null)
        {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");

            for (String key : intent.getExtras().keySet())
            {
                builder.addData(key, intent.getExtras().get(key).toString());
            }



           onMessageReceived(builder.build());
        }
        else
        {
            super.handleIntent(intent);
        }
    }
    catch (Exception e)
    {
        super.handleIntent(intent);
    }
}
Franc
la source
J'essaie d'implémenter votre solution, mais la méthode handleIntent () est finale dans ma version du SDK (SDK 27), donc je ne peux pas la remplacer dans mon service ...
matdev
Oui mais ce n'est pas ma faute ou aucune raison de donner -1 !!! Très arrogant. Cela fonctionne jusqu'à firebase 11.4.2 puis google l'a changé (a rendu cette méthode définitive). Alors maintenant, vous devez programmer votre propre solution avec notification.
Frank
Je n'ai pas donné un -1 mais un +1!
matdev
Vous enregistrez mon travail: P
amitabha2715
2

Essaye ça:

public void handleIntent(Intent intent) {
    try {
        if (intent.getExtras() != null) {
            RemoteMessage.Builder builder = new RemoteMessage.Builder("MyFirebaseMessagingService");
            for (String key : intent.getExtras().keySet()) {
            builder.addData(key, intent.getExtras().get(key).toString());
        }
            onMessageReceived(builder.build());
        } else {
            super.handleIntent(intent);
        }
    } catch (Exception e) {
        super.handleIntent(intent);
    }
}
user3587828
la source
handleIntent n'est plus utilisé dans Firebase: 11.8.0 et versions supérieures.
Shihab Uddin
1

J'ai eu ce problème (l'application ne veut pas s'ouvrir lors de la notification, cliquez si l'application est en arrière-plan ou fermée), et le problème n'était pas valide click_actiondans le corps de notification, essayez de le supprimer ou de le changer en quelque chose de valide.

Octavian Lari
la source
1

Le point qui mérite d'être souligné est que vous devez utiliser le message de données - clé de données uniquement - pour obtenir le gestionnaire onMessageReceived appelé même lorsque l'application est en arrière-plan. Vous ne devriez pas avoir d'autre clé de message de notification dans votre charge utile, sinon le gestionnaire ne sera pas déclenché si l'application est en arrière-plan.

Il est mentionné (mais pas tellement souligné dans la documentation FCM) ici:

https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages

Utilisez votre serveur d'applications et l'API du serveur FCM: définissez uniquement la clé de données . Peut être pliable ou non pliable.

New York
la source
1

Le backend avec lequel je travaille utilise des messages de notification et non des messages de données. Donc, après avoir lu toutes les réponses, j'ai essayé de récupérer les extras du bundle de l'intention qui vient de l'activité lancée. Mais peu importe de quelles clés j'ai essayé de récupérergetIntent().getExtras(); , la valeur était toujours nulle.

Cependant, j'ai finalement trouvé un moyen d'envoyer des données à l'aide de messages de notification et de les récupérer à partir de l'intention.

La clé ici est d'ajouter la charge utile de données au message de notification.

Exemple:

{
    "data": {
        "message": "message_body",
        "title": "message_title"
    },
    "notification": {
        "body": "test body",
        "title": "test title"
    },
    "to": "E4An.."
}

Après cela, vous pourrez obtenir vos informations de cette manière:

intent.getExtras().getString("title") sera message_title

et intent.getExtras().getString("message") seramessage_body

Référence

Vito Valov
la source
1

Si votre problème est lié à l'affichage de Big Image, c'est-à-dire si vous envoyez une notification push avec une image de la console Firebase et qu'elle affiche l'image uniquement si l'application est au premier plan. La solution à ce problème consiste à envoyer un message push avec uniquement un champ de données. Quelque chose comme ça:

{ "data": { "image": "https://static.pexels.com/photos/4825/red-love-romantic-flowers.jpg", "message": "Firebase Push Message Using API" "AnotherActivity": "True" }, "to" : "device id Or Device token" }
Arun
la source
vous avez perdu la virgule avant "AnotherActivity". Mon androïde vibre mais vraiment rien montré (pas de texte, pas d'image, pas de push).
jekaby
1

Lorsque le message est reçu et que votre application est en arrière-plan, la notification est envoyée à l'intention supplémentaire de l'activité principale.

Vous pouvez vérifier la valeur supplémentaire dans la fonction oncreate () ou onresume () de l'activité principale.

Vous pouvez vérifier les champs comme les données, la table, etc. (celui spécifié dans la notification)

par exemple, j'ai envoyé en utilisant des données comme clé

public void onResume(){
    super.onResume();
    if (getIntent().getStringExtra("data")!=null){
            fromnotification=true;
            Intent i = new Intent(MainActivity.this, Activity2.class);
            i.putExtra("notification","notification");
            startActivity(i);
        }

}
Sanjeev S
la source
0

J'avais le même problème et j'ai creusé un peu plus à ce sujet. Lorsque l'application est en arrière-plan, un message de notification est envoyé dans la barre d'état système, MAIS un message de données est envoyé à onMessageReceived()
Voir https://firebase.google.com/docs/cloud-messaging/downstream#monitor-token-generation_3
et https://github.com/firebase/quickstart-android/blob/master/messaging/app/src/main/java/com/google/firebase/quickstart/fcm/MyFirebaseMessagingService.java

Pour vous assurer que le message que vous envoyez, les documents indiquent: " Utilisez votre serveur d'application et l'API du serveur FCM: définissez la clé de données uniquement. Peut être pliable ou non pliable " .
Voir https://firebase.google.com/ docs / cloud-messaging / concept-options # notifications_and_data_messages

Eric B.
la source
0

Il existe deux types de messages: les messages de notification et les messages de données. Si vous envoyez uniquement un message de données, c'est sans objet de notification dans votre chaîne de message. Il serait invoqué lorsque votre application en arrière-plan.

Shongsu
la source
0

Vérifiez la réponse de @Mahesh Kavathiya. Pour mon cas, dans le code serveur a seulement comme ceci:

{
"notification": {
  "body": "here is body",
  "title": "Title",
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

Vous devez changer pour:

{
 "data": {
  "body": "here is body",
  "title": "Title",
  "click_action": "YOUR_ACTION"
 },
"notification": {
  "body": "here is body",
  "title": "Title"
 },
 "to": "sdfjsdfonsdofoiewj9230idsjkfmnkdsfm"
}

Ensuite, dans le cas où l'application en arrière-plan, l'intention d'activité par défaut supplémentaire obtiendrait des "données"

Bonne chance!

huynq0911
la source
-1

Remplacez simplement la méthode OnCreate de FirebaseMessagingService. Il est appelé lorsque votre application est en arrière-plan:

public override void OnCreate()
{
    // your code
    base.OnCreate();
}
Renzo Ciot
la source
Cette réponse pourrait être plus utile si vous pouviez ajouter une explication et un lien vers une documentation. Pouvez-vous nous dire en quoi cela est censé aider?
kilokahn
@kilokahn Pouvez-vous m'expliquer ce que vous ne comprenez pas? la méthode indiquée doit être insérée dans le code qui fait partie de la question et répond entièrement à la question. Le code est pour Xamarin, mais vous pouvez simplement convertir en java.
Renzo Ciot
AFAIK La documentation officielle ( firebase.google.com/docs/cloud-messaging/android/client ) ne parle pas de remplacer OnCreate dans un service étendant FirebaseMessagingService - si vous avez accès à une documentation qui le fait, vous pouvez peut-être partager un lien? De plus, d'après votre réponse, il n'est pas clair comment le remplacement de onCreate résout le problème de la non-appel de onMessageReceived lorsque la notification est cliquée - d'où la demande d'informations supplémentaires.
kilokahn
La documentation ne mentionne pas le remplacement de la méthode OnCreate, mais cela fonctionne parce que je l'utilise en production. Le code que vous souhaitez insérer dans la méthode onMessageReceived et qui sert évidemment à effectuer certaines opérations d'arrière-plan peut être effectué sur OnCreate.
Renzo Ciot
Dans ce cas, expliquer le fait que cela a fonctionné pour vous peut s'avérer plus utile que de simplement lister la solution. En outre, un comportement non documenté est susceptible d'arrêter arbitrairement de travailler avec des mises à jour, et quelqu'un qui les utilise doit être prêt à retravailler leur code quand il le fait. Cette clause de non-responsabilité doit être
insérée
-1

Il existe 2 types de notifications push Firebase :

1- Message de notification (Message affiché) -> - 1.1 Si vous choisissez cette variante, le système d'exploitation se créera automatiquement une notification si l'application est en arrière - plan et transmettra les données dans le intent. Ensuite, c'est au client de gérer ces données.

- 1.2 Si l'application est au premier plan, la notification sera reçue via callback-functionle FirebaseMessagingServiceet c'est au client de la gérer.

2- Messages de données (jusqu'à 4k données) -> Ces messages sont utilisés pour envoyer uniquement des données au client (en silence) et c'est au client de les gérer pour les deux cas fond / premier plan via la fonction de rappel dans FirebaseMessagingService

C'est selon les documents officiels: https://firebase.google.com/docs/cloud-messaging/concept-options

Balflear
la source