325 votes

Firebase onMessageReceived n'est pas appelé lorsque l'application est en arrière-plan

Je travaille avec Firebase et je teste l'envoi de notifications à mon application depuis mon serveur alors que l'application est en arrière-plan. La notification est envoyée avec succès, elle apparaît même dans 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 je l'ai testé alors que mon application était au premier plan, la méthode onMessageReceived a été appelée et tout a bien fonctionné. Le problème survient lorsque l'application fonctionne en arrière-plan.

Est-ce que c'est le comportement souhaité ou y a-t-il un moyen de corriger 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"));
        }
    }
}

0 votes

En plus du corps json, où est votre onTokenRefresh code ? Avez-vous complété le Configuration Android ?

4 votes

Que voulez-vous dire par le corps json de la notification ? De plus, mon code onTokenRefresh se trouve dans mon service FirebaseInstanceID.

0 votes

Pouvez-vous afficher l'échantillon de la charge utile que vous envoyez ?

199voto

Arthur Thompson Points 6455

Les messages de notification sont transmis à votre callback onMessageReceived uniquement lorsque votre application est au premier plan. Si votre application est en arrière-plan ou fermée, un message de notification est affiché dans le centre de notification, et tout message de notification reçu par le callback onMessageReceived est envoyé à la callback onMessageReceived. les données de ce message sont transmises à l'intention qui est lancé lorsque l'utilisateur appuie sur la notification.

Vous pouvez spécifier un click_action dans votre JSON pour indiquer l'intention qui doit être lancée lorsque l'utilisateur touche la notification. L'activité principale est utilisée si aucune click_action n'est spécifiée.

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

getIntent().getExtras();

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

Pour en savoir plus sur le message de notification, voir docs .

7 votes

Existe-t-il un moyen de définir le click_action lorsque j'utilise la console de notification Firebase ?

7 votes

Ok, mais que se passe-t-il si l'application est tuée (pas de premier plan ou d'arrière-plan) ?

1 votes

Vous pouvez le tester par vous-même. Envoyez un message alors que votre application n'est pas en cours d'exécution. Le message devrait quand même être remis au téléphone cible.

190voto

Zohab Ali Points 1028

Retirer notification champ complètement de votre demande de serveur. Envoyer sólo data et le traiter dans onMessageReceived() sinon votre onMessageReceived() ne sera pas déclenché lorsque l'application est en arrière-plan ou tuée.

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

Voici ce que j'envoie depuis le serveur

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

Vous pouvez donc recevoir vos données en onMessageReceived(RemoteMessage message) comme ça....let dire que je dois obtenir une identité

Object obj = message.getData().get("id");
        if (obj != null) {
            int id = Integer.valueOf(obj.toString());
        }

11 votes

J'ai constaté que si j'envoie uniquement un message de données, l'application qui est effacée du gestionnaire des tâches ne pourra pas recevoir de notification.

2 votes

C'était la solution pour moi pour recevoir des messages en arrière-plan !

0 votes

Cela signifie-t-il que dans la console, nous ne pouvons pas traiter les données de notification et que si nous envoyons une requête HTTP pure sans la section de notification, nous pouvons traiter les données de notification ? J'ai commencé à utiliser la console Firebase en pensant que je pourrais faire cela, donc je retourne à la notification HTTP POST :-(

69voto

manas.abrol Points 631

Cette méthode handleIntent() a été dépréciée, donc la gestion d'une notification peut être faite comme ci-dessous :

  1. État du premier plan : Le clic de la notification se dirigera vers l'activité de l'intention en attente que vous fournissez lors de la création pro-grammatique d'une notification, car elle est généralement créée avec les données utiles de la notification.

  2. État d'arrière-plan/d'exécution - Dans ce cas, le système crée lui-même une notification basée sur les données utiles de la notification. 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 de l'intention dans n'importe quelle méthode du cycle de vie.

1 votes

Merci ! !! J'ai perdu quelques jours sur ce problème et celui-ci m'a sauvé.

0 votes

Vraiment la solution parfaite !

0 votes

La solution parfaite que je cherchais ..... tu as sauvé ma journée, mec .........

44voto

mesuk 08308 Points 16

Voici des concepts plus clairs sur le message firebase. Je l'ai trouvé dans leur équipe de support.

Firebase dispose de 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 envoyés dans la barre d'état système. Si l'application est en avant-plan, les messages sont traités par onMessageReceived() o didReceiveRemoteNotification les rappels. Il s'agit essentiellement de ce que l'on appelle les messages d'affichage.

Messages de données : Sur la plateforme Android, le message de données peut fonctionner en arrière-plan et en avant-plan. Le message de données sera traité par onMessageReceived(). Une note spécifique à la plateforme serait ici : Sur Android, la charge utile des données peut être récupérée dans l'Intent utilisé pour lancer votre activité. En d'autres termes, si vous avez "click_action":"launch_Activity_1" vous pouvez récupérer cette intention par le biais de getIntent() de seulement Activity_1 .

Messages contenant à la fois des notifications et des données : Lorsqu'elles sont en arrière-plan, les apps reçoivent la charge utile de la notification dans la zone de notification et ne traitent la charge utile de données que lorsque l'utilisateur tape sur la notification. Au premier plan, votre application reçoit un objet message avec les deux données utiles disponibles. Deuxièmement, le paramètre click_action est souvent utilisé dans les données utiles de notification et non dans les données utiles. 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 mettre en œuvre une logique personnalisée pour qu'il fonctionne comme prévu.

Je vous recommande également d'utiliser la méthode onMessageReceived (voir Message de données) pour extraire le paquet de données. À partir de 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é du serveur, la notification de firebase doit avoir le format suivant :

Le côté serveur doit envoyer "notification" objet. Le manque d'objet "notification" dans mon TargetActivity Je n'ai pas reçu de message en utilisant getIntent() .

Le format correct du message 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é dans leur équipe de support.

Pour plus d'informations, visitez mon ce fil y ce fil

6 votes

Il convient de noter que les "messages de données" ne seront pas reçus si l'appareil est en mode "doze" profond (introduit dans Android 7.0). soyez prudent avec ces messages !

32voto

Koot Points 327

J'ai eu le même problème. Il est plus facile d'utiliser le "message de données" plutôt que la "notification". Le message de données charge toujours la classe onMessageReceived.

Dans cette classe, vous pouvez créer votre propre notification avec le constructeur 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());
    }

7 votes

Merci J'ai modifié mon code serveur et utilisé "data" au lieu de "notification" et maintenant cela fonctionne parfaitement,

5 votes

@Koot cela ne fonctionne que si l'application est au premier plan et pas si elle est en arrière plan. pouvez-vous m'aider à déclencher cet événement dans les deux cas ?

0 votes

@AnantShah, à quoi ressemble votre POST vers le serveur Firebase ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X