web-dev-qa-db-fra.com

Comment gérer les notifications lorsque l'application est en arrière-plan dans Firebase

Voici mon manifeste

    <service Android:name=".fcm.PshycoFirebaseMessagingServices">
        <intent-filter>
            <action Android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <service Android:name=".fcm.PshycoFirebaseInstanceIDService">
        <intent-filter>
            <action Android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

Lorsque l'application est en arrière-plan et que la notification arrive, la notification par défaut arrive et n'exécute pas mon code onMessageReceived.

Voici mon code onMessageReceived. Cela appelle si mon application est exécutée au premier plan, pas si l'application est en arrière-plan. Comment exécuter ce code lorsque l'application est en arrière-plan aussi?

// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // TODO(developer): Handle FCM messages here.
    // If the application is in the foreground handle both data and notification messages here.
    // Also if you intend on generating your own notifications as a result of a received FCM
    // message, here is where that should be initiated. See sendNotification method below.
    data = remoteMessage.getData();
    String title = remoteMessage.getNotification().getTitle();
    String message = remoteMessage.getNotification().getBody();
    String imageUrl = (String) data.get("image");
    String action = (String) data.get("action");
    Log.i(TAG, "onMessageReceived: title : "+title);
    Log.i(TAG, "onMessageReceived: message : "+message);
    Log.i(TAG, "onMessageReceived: imageUrl : "+imageUrl);
    Log.i(TAG, "onMessageReceived: action : "+action);

    if (imageUrl == null) {
        sendNotification(title,message,action);
    } else {
        new BigPictureNotification(this,title,message,imageUrl,action);
    }
}
// [END receive_message]
311
Parth Patel

1. Pourquoi cela se passe-t-il?

Il existe deux types de messages dans FCM (Firebase Cloud Messaging):

  1. Messages d'affichage: ces messages déclenchent le rappel onMessageReceived() uniquement lorsque votre application est dans foreground
  2. Messages de données: ces messages déclenchent le rappel onMessageReceived()même si votre application est en mode premier plan/arrière-plan/tué

L’équipe de Firebase n’a pas développé d’UI pour envoyer data-messages à vos appareils, pour le moment .

2. Comment faire?

Pour ce faire, vous devez exécuter une demande POST à l'URL suivante:

POSThttps://fcm.googleapis.com/fcm/send

En-têtes

  • Clé:Content-Type, valeur:application/json
  • Clé:Authorization, Valeur:key=<your-server-key>

Corps utilisant des sujets

{
    "to": "/topics/my_topic",
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     }
}

Ou si vous voulez l'envoyer à des appareils spécifiques

{
    "data": {
        "my_custom_key": "my_custom_value",
        "my_custom_key2": true
     },
    "registration_ids": ["{device-token}","{device2-token}","{device3-token}"]
}


REMARQUE: Assurez-vous que vous n'ajoutez pas clé JSON notification 
NOTE: Pour obtenir votre clé de serveur, vous pouvez la trouver dans la console Firebase: Your project -> settings -> Project settings -> Cloud messaging -> Server Key

3. Comment gérer le message de notification Push?

Voici comment vous gérez le message reçu:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String myCustomKey = data.get("my_custom_key");

     // Manage data
}
526
Antonio

Pour que la bibliothèque firebase appelle votre onMessageReceived () dans les cas suivants

  1. App au premier plan
  2. App en arrière-plan
  3. App a été tué

vous ne devez pas insérer de "notification" de clé JSON dans votre demande auprès de l'API firebase, mais plutôt utiliser "données" (voir ci-dessous).

Le message suivant n'appelle pas votre onMessageReceived () lorsque votre application est en arrière-plan ou tuée, et vous ne pouvez pas personnaliser votre notification.

{
   "to": "/topics/journal",
   "notification": {
   "title" : "title",
   "text": "data!",
   "icon": "ic_notification"
    }
}

mais au lieu de cela cela fonctionnera

{
  "to": "/topics/dev_journal",
   "data": {
       "text":"text",
       "title":"",
       "line1":"Journal",
       "line2":"刊物"
   }
} 

En gros, le message est envoyé dans l'argument RemoteMessage avec votre objet de données en tant que carte. Vous pouvez ensuite gérer la notification dans onMessageReceived comme dans l'extrait de code ici

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();

     //you can get your text message here.
     String text= data.get("text");


     NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
        // optional, this is to make beautiful icon
             .setLargeIcon(BitmapFactory.decodeResource(
                                    getResources(), R.mipmap.ic_launcher))  
        .setSmallIcon(smallIcon)  //mandatory
      .......
    /*You can read more on notification here:
    https://developer.Android.com/training/notify-user/build-notification.html
    https://www.youtube.com/watch?v=-iog_fmm6mE
    */
}
127

Je pense que toutes les réponses sont incomplètes, mais qu’elles ont toutes un élément nécessaire pour traiter une notification contenant des données lorsque votre application est en arrière-plan.

Suivez ces étapes et vous pourrez traiter vos notifications lorsque votre application est en arrière-plan.

1.Ajouter un filtre d'intention comme ceci:

<activity Android:name=".MainActivity">
      <intent-filter>
           <action Android:name=".MainActivity" />
           <category Android:name="Android.intent.category.DEFAULT" />
      </intent-filter>
</activity>

à une activité pour laquelle vous souhaitez traiter les données de notification.

  1. Envoyer des notifications au format suivant:

    { 
     "notification" : {
            "click_action" : ".MainActivity", 
            "body" : "new Symulti update !", 
            "title" : "new Symulti update !", 
            "icon" : "ic_notif_symulti" }, 
     "data": { ... },
     "to" : "c9Vaa3ReGdk:APA91bH-AuXgg3lDN2WMcBrNhJZoFtYF9" }
    

La clé ici est d'ajouter 

"click_action" : ".MainActivity"

où .MainActivity est l'activité avec le filtre d'intention que vous avez ajouté à l'étape 1.

  1. Récupère les informations "data" de la notification dans le onCreate de ".MainActivity":

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //get notification data info
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
           //bundle must contain all info sent in "data" field of the notification
        }
    }
    

Et cela devrait être tout ce que vous devez faire. J'espère que cela aide quelqu'un :)

74
Daniel S.

Selon docs

Gérer les messages dans une application avec arrière-plan

Lorsque votre application est en arrière-plan, Android dirige la notification messages dans la barre d'état système. Un utilisateur tapant sur la notification ouvre le fichier lanceur d'applications par défaut.

Cela inclut les messages contenant à la fois des notifications et des données charge utile. Dans ces cas, la notification est transmise au périphérique .__ de l'appareil. dans la barre d'état système, et la charge de données est livrée dans les extras du intention de votre activité de lanceur.

Si vous souhaitez ouvrir votre application et effectuer une action spécifique, définissez click_action dans la charge de notification et le mapper à une intention filtrer dans l'activité que vous souhaitez lancer. Par exemple, définissez click_action sur OPEN_ACTIVITY_1 pour déclencher un filtre d'intention tel que le Suivant:

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

Modifier :

Basé sur ce thread

Vous ne pouvez pas définir la charge click_action à l'aide de la console Firebase. Vous pouvez essayer de tester avec une commande curl ou un serveur http personnalisé

curl --header "Authorization: key=<YOUR_KEY_GOES_HERE>" 
     --header Content-Type:"application/json" https://fcm.googleapis.com/fcm/send  
     -d "{\"to\":\"/topics/news\",\"notification\": 
         {\"title\": \"Click Action Message\",\"text\": \"Sample message\",
            \"click_action\":\"OPEN_ACTIVITY_1\"}}"
31
Shubhank

Selon la documentation de firebase dans envoyer en aval à l'aide de firebase , il existe 2 types de données utiles:

  1. Les données

    Ce paramètre spécifie les paires clé-valeur personnalisées de la charge utile du message . L'application client est responsable du traitement des messages de données. Les messages de données ont uniquement des paires clé-valeur personnalisées.

  2. notification

    Ce paramètre spécifie les paires clé-valeur prédéfinies et visibles par l'utilisateur de la charge de notification. FCM affiche automatiquement le message aux périphériques des utilisateurs finaux pour le compte de l'application client. Les messages de notification ont un ensemble prédéfini de clés visibles par l'utilisateur.

Lorsque vous êtes au premier plan, vous pouvez obtenir les données dans FCM à l'aide de onMessageReceived (), vous pouvez obtenir vos données à partir de data payload.

data = remoteMessage.getData();
String customData = (String) data.get("customData");

Lorsque vous êtes en arrière-plan, FCM affiche une notification dans la barre d'état système en fonction des informations de la charge notification. Le titre, le message et l'icône utilisés pour la notification dans la zone de notification proviennent de la charge notification.

{
  "notification": {
        "title" : "title",
        "body"  : "body text",
        "icon"  : "ic_notification",
        "click_action" : "OPEN_ACTIVITY_1"
       }
}

Ces données utiles notification sont utilisées lorsque vous souhaitez afficher automatiquement des notifications dans la barre d'état système lorsque votre application est en arrière-plan . Pour obtenir les données de notification lorsque votre application est en arrière-plan, vous devez ajouter click_action dans notification. charge utile.

Si vous souhaitez ouvrir votre application et effectuer une action spécifique [en tâche de fond], définissez click_action dans le contenu de notification et mappez-le à un filtre d'intention dans l'activité que vous souhaitez lancer. Par exemple, définissez click_action sur OPEN_ACTIVITY_1 pour déclencher un filtre d'intention semblable à celui-ci:

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

Placez ce filtre d'intention sur votre manifeste, dans la balise d'application. Lorsque vous cliquez sur la notification, l'application est ouverte et passe directement à l'activité que vous définissez dans click_action, dans ce cas, "OPEN_ACTIVTY_1" . Dans cette activité, vous pouvez obtenir les données en:

Bundle b = getIntent().getExtras();
String someData = b.getString("someData");

J'utilise FCM pour mon application Android et utilise à la fois la charge utile . Voici l'exemple JSON que j'utilise:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification", "click_action" : "OPEN_ACTIVITY_1"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}
25
Hendy Evan

Depuis le display-messages qui sont envoyés depuis Firebase Notification UI ne fonctionne que si votre application est au premier plan. Pour data-messages, il est nécessaire d’appeler POST vers FCM

Pas

  1. Installer l’extension Google Chrome du client de repos avancé  enter image description here

  2. Ajouter les en-têtes suivants 

    Clé: type de contenu, valeur: application/json

    Clé: autorisation, valeur: clé = "votre clé serveur"  enter image description here

  3. Ajouter le corps

    • Si vous utilisez des sujets:

      {
          "to" : "/topics/topic_name",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
          }
      }
      
    • Si vous utilisez un identifiant d'enregistrement:

      {
          "registration_ids" : "[{"id"},{id1}]",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
           }
      }
      

C'est tout!. Écoutez maintenant le callback onMessageReceived comme d'habitude.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) { 
     Map<String, String> data = remoteMessage.getData();
     String value1 = data.get("key1");
     String value2 = data.get("key2");
}
19
Anirudh Ramanan

Pour capturer le message en arrière-plan, vous devez utiliser une variable BroadcastReceiver

public class FirebaseDataReceiver extends WakefulBroadcastReceiver {

    private final String TAG = "FirebaseDataReceiver";

    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "I'm in!!!");
        Bundle dataBundle = intent.getBundleExtra("data");
        Log.d(TAG, dataBundle.toString());
    }
}

et ajoutez ceci à votre manifeste:

<receiver
      Android:name="MY_PACKAGE_NAME.FirebaseDataReceiver"
      Android:exported="true"
      Android:permission="com.google.Android.c2dm.permission.SEND">
        <intent-filter>
            <action Android:name="com.google.Android.c2dm.intent.RECEIVE" />
        </intent-filter>
</receiver>
15
Romulano
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

n'est pas appelé à chaque fois qu'il est appelé uniquement lorsque l'application est en forground

il y a une méthode de substitution cette méthode est appelée à chaque fois, quelle que soit l'application située au premier plan, en arrière-plan ou supprimée, mais cette méthode est disponible avec cette version de firebase api 

c'est la version que vous devez importer de Gradle

compile 'com.google.firebase:firebase-messaging:10.2.1'

c'est la méthode

@Override
public void handleIntent(Intent intent) {
    super.handleIntent(intent);

    // you can get ur data here 
    //intent.getExtras().get("your_data_key") 


}

avec api firebase précédent cette méthode n'était pas là alors dans ce cas base de feu se gérer quand l'application est en arrière-plan .... maintenant vous avez cette méthode tout ce que vous voulez faire ... vous pouvez le faire ici dans cette méthode ..... 

si vous utilisez la version précédente, l'activité par défaut commence Dans ce cas, vous pouvez obtenir les données de la même manière. 

if(getIntent().getExtras() != null && getIntent().getExtras().get("your_data_key") != null) {
String strNotificaiton = getIntent().getExtras().get("your_data_key").toString();

// fais ce que tu veux ... }

généralement c'est la structure du serveur que nous recevons dans la notification 

{
    "notification": {
        "body": "Cool offers. Get them before expiring!",
        "title": "Flat 80% discount",
        "icon": "appicon",
        "click_action": "activity name" //optional if required.....
    },
    "data": {
        "product_id": 11,
        "product_details": "details.....",
        "other_info": "......."
    }
}

c’est à vous de décider comment vous voulez donner cette clé de données ou de donner une notification de ce que vous pouvez donner ....... tout ce que vous donnerez ici avec la même clé vous obtiendrez ces données ..... .... 

il y a peu de cas si ur n'envoie pas d'action de clic dans ce cas, lorsque tu cliques sur une notification, l'activité par défaut s'ouvre, mais si tu veux ouvrir ton activité spécifique lorsque l'application est en arrière-plan, tu peux appeler ton activité depuis cette méthode sur la méthode handleIntent est appelé à chaque fois 

15
Avinash Jadaun

Selon les docs: 17 mai 2017

Lorsque votre application est dans le background, Android dirige les messages de notification vers la barre d'état système. Un utilisateur appuie sur le notification ouvre le lanceur app par défaut.

Cela inclut les messages contenant à la fois notification et data payload (et tous les messages envoyés depuis la console Notifications). Dans ces Dans certains cas, la notification est transmise à la barre d'état système du périphérique et la charge de données est livrée dans les extras de l'intention de votre Activité du lanceur.

Donc, vous devriez utiliser à la fois la notification de charge utile et les données:

{
  "to": "FCM registration ID",
  "notification": {
    "title" : "title",
    "body"  : "body text",
    "icon"  : "ic_notification"
   },
   "data": {
     "someData"  : "This is some data",
     "someData2" : "etc"
   }
}

Il n'est pas nécessaire d'utiliser click_action.Vous devriez simplement obtenir l'exras de l'intention de l'activité LAUNCHER 

<activity Android:name=".MainActivity">
        <intent-filter>
            <category Android:name="Android.intent.category.LAUNCHER" />
        </intent-filter>
</activity>

Le code Java doit être sur la méthode onCreate sur MainActivity:

Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {
    Bundle extras = intent.getExtras();
    String someData= extras.getString("someData");
    String someData2 = extras.getString("someData2");
}

Vous pouvez tester les données de notification de charge utile + à partir de Console de notifications Firebase . N'oubliez pas de remplir les champs de données personnalisés dans la section Options avancées

9
Mihuilk

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

Firebase a trois types de messages:

Messages de notification: le message de notification fonctionne en arrière-plan ou en avant-plan. Lorsque l'application est en arrière-plan, les messages de notification sont remis à la barre d'état système. Si l'application est au premier plan, les messages sont traités par des rappels onMessageReceived() ou didReceiveRemoteNotification. Ce sont essentiellement ce que l’on appelle les messages d’affichage.

Messages de données: sur la plate-forme Android, les messages de données peuvent fonctionner à l'arrière-plan et à l'avant-plan. Le message de données sera traité par onMessageReceived (). Voici une note spécifique à la plate-forme: Sous Android, la charge de données peut être récupérée dans l’intention utilisée pour lancer votre activité. Pour élaborer, si vous avez "click_action":"launch_Activity_1", vous pouvez récupérer cette intention via getIntent() à partir de Activity_1 uniquement.

Messages contenant à la fois des charges de notification et des données: en arrière-plan, les applications reçoivent la charge de notification dans la barre de notification et ne gèrent la charge 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 de notification et non dans la charge de données. S'il est utilisé dans les données, ce paramètre est traité comme une paire clé-valeur personnalisée. Par conséquent, vous devez implémenter une logique personnalisée pour que cela fonctionne comme prévu.

De plus, je vous recommande d'utiliser la méthode onMessageReceived (voir Message de données) pour extraire le paquet de données. A 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 fournir plus de clarté.

Pour plus d'informations, visitez mon ce fil de discussion

9
Md. Sajedul Karim

Réponse mise à jour 2017

Voici une réponse claire de la docs à ce sujet:

 enter image description here

8
pulp_fiction

J'ai compris les scénarios,

Lorsque app est dans foreground, onMessageReceived () la méthode est appelée à partir de FirebaseService . Ainsi, waitingIntent défini dans la classe de service sera appelé.

Et quand app est dans background, la première activité est appelée.

Maintenant, si vous utilisez une activité splash , alors doit garder à l'esprit le splashactivity sera appelé, sinon s'il n'y a pas de splashActivity, alors quelle que soit la première activité, elle sera appelée.

Ensuite, vous devez vérifier getIntent () du firstActivity pour voir s’il contient un paquet bundle . Si tout va bien, vous verrez que le paquet contient des valeurs renseignées. Si la valeur est dans La balise data envoyée par le serveur ressemble à ceci, 

"data": {
    "user_name": "arefin sajib",
    "value": "user name notification"
  }

Ensuite, dans la première activité, vous verrez que Il y a une intention valide (getIntent () n’est pas null), un bundle valide et un bundle, le JSON complet mentionné ci-dessus avec data commetouche.

Pour ce scénario, le code pour l'extraction de la valeur ressemblera à ceci,

    if(getIntent()!=null){
            Bundle bundle = getIntent().getExtras();
            if (bundle != null) {
                try {
                   JSONObject object = new JSONObject(bundle.getStringExtra("data"));
String user_name = object.optString("user_name");

                } catch (JSONException e) {
                    e.printStackTrace();
                }


            }
        }
6

Résumé simple comme ça

  • si votre application est en cours d'exécution;

    onMessageReceived()
    

est des déclencheurs.

  • si votre application ne fonctionne pas (tuée en balayant);

    onMessageReceived()
    

n'est pas déclenché et livré par direclty. Si vous avez une paire clé/valeur spéciale. Ils ne fonctionnent pas parce que onMessageReceived () ne fonctionne pas. 

J'ai trouvé ça comme ça;

Dans votre activité de lanceur, mettez cette logique,

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState, R.layout.activity_splash);

    if (getIntent().getExtras() != null && getIntent().getExtras().containsKey("PACKAGE_NAME")) {

        // do what you want

        // and this for killing app if we dont want to start
        Android.os.Process.killProcess(Android.os.Process.myPid());

    } else {

        //continue to app
    }
}

dans ce bloc, recherchez vos clés en fonction de l'interface utilisateur de firebase.

Dans cet exemple, ma clé et ma valeur comme ci-dessus; (désolé pour la langue =))  enter image description here

Quand mon code fonctionne, je reçois "com.rda.note". 

Android.os.Process.killProcess(Android.os.Process.myPid());

avec cette ligne de code, j'ai fermé mon application et ouvert Google Play Market

code heureux =)

6
Arda

Merci à vous tous pour vos réponses. Mais j'ai résolu cela en envoyant message de données au lieu d'envoyer Notification. Code serveur

<?php
$url = "https://fcm.googleapis.com/fcm/send";
$token = "C-l6T_a7HouUK****";
$serverKey = "AAAAaOcKS00:********";
define( 'API_ACCESS_KEY', $serverKey );
$registrationIds = array($token);
// prep the bundle

$msg = array

(
 'message'  => 'here is a message. message',
 'title'        => 'This is a title. title',
 'subtitle' => 'This is a subtitle. subtitle',
 'tickerText'   => 'Ticker text here...Ticker text here...Ticker text 
 here',
 'vibrate'  => 1,
 'sound'        => 1,
 'largeIcon'    => 'large_icon',
 'smallIcon'    => 'small_icon'

);

$fields = array

(
  'registration_ids'    => $registrationIds,
  'data'            => $msg

);
$headers = array

(
  'Authorization: key=' . API_ACCESS_KEY,
 'Content-Type: application/json'

);


$ch = curl_init();

curl_setopt( $ch,CURLOPT_URL, 'https://Android.googleapis.com/gcm/send' 
);

curl_setopt( $ch,CURLOPT_POST, true );

curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );

curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );

curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );

curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );

$result = curl_exec($ch );

curl_close( $ch );

echo $result;

?>

Et pris les données dans onMessageReceived

public class MyFirebaseMessagingService extends FirebaseMessagingService     {

  private static final String TAG = "MyFirebaseMsgService";

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Log.d(TAG, "From: " + remoteMessage.getFrom());

    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());

      sendNotification(remoteMessage.getData().get("message"));
     }
   // Check if message contains a notification payload.
    else if (remoteMessage.getNotification() != null) {
        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
    sendNotification(remoteMessage.getNotification().getBody());
    }


}
   private void sendNotification(String messageBody) {
    Intent intent = new Intent(this, Notify.class).putExtra("msg",messageBody);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);

    String channelId = "idddd";
    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(MyFirebaseMessagingService.this)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .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());
}
}
3
Android Sanaullah

Le moyen le plus simple d’envoyer des messages même si l’application est en arrière-plan et au premier plan est le suivant: - Pour envoyer un message à l’aide de l’API, vous pouvez utiliser un outil appelé Client AdvancedREST, c’est une extension chrome et envoyer un message avec les éléments suivants: paramètres.

Rest client tool Link: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo

utilisez cette URL: - https://fcm.googleapis.com/fcm/send Content-Type: application/json Authorization: key = Votre clé de serveur De ou Authoization key (voir ci-dessous réf. )

{ "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"
}

La clé d'autorisation peut être obtenue en visitant la console des développeurs Google et en cliquant sur le bouton Informations d'identification dans le menu de gauche pour votre projet. Parmi les clés API répertoriées, la clé de serveur sera votre clé d'autorisation.

Et vous devez mettre tokenID du destinataire dans la section «à» de votre demande POST envoyée à l'aide de l'API.

2
Syed Danish Haider

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

Voici ce que j'envoie depuis le serveur:

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

Ainsi, vous pouvez recevoir vos données dans onMessageReceived(RemoteMessage message) comme ceci: (disons que je dois obtenir l'identifiant)

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

Et de même, vous pouvez obtenir toutes les données que vous avez envoyées du serveur dans onMessageReceived().

2
Zohab Ali

vous voulez travailler sur MessageReceived (RemoteMessage remoteMessage) en arrière-plan, envoyez uniquement la partie de notification de la partie de données suivante: 

"data":    "image": "",    "message": "Firebase Push Message Using API", 

"AnotherActivity": "True", "à": "ID de périphérique ou jeton de périphérique" 

Par cela, onMessageRecivied est un appel en arrière-plan et au premier plan, il n'est pas nécessaire de gérer la notification à l'aide de la barre de notification pour votre activité de lancement. Gérer les données utiles en utilisant ceci:
public void onMessageReceived (RemoteMessage remoteMessage) if (remoteMessage.getData (). size ()> 0) Log.d (TAG, "Données utiles du message:" + remoteMessage.getData ()); 

1
user3385125

June 2018 Réponse - 

Vous devez vous assurer qu'il n'y a pas de mot clé "notification" dans le message. N'incluez que les "données", et l'application sera capable de gérer le message dans onMessageReceived, même en arrière-plan ou tué.

Utilisation des fonctions de nuage:

const message = {
    token: token_id,   // obtain device token id by querying data in firebase
    data: {
       title: "my_custom_title",
       body:  "my_custom_body_message"
       }
    }


return admin.messaging().send(message).then(response => {
    // handle response
});

Puis dans votre onMessageReceived (), dans votre classe étendant com.google.firebase.messaging.FirebaseMessagingService:

if (data != null) {
  Log.d(TAG, "data title is: " + data.get("title");
  Log.d(TAG, "data body is: " + data.get("body");
}

// build notification using the body, title, and whatever else you want.
1
Jeff Padgett

Réponse mise à jour selon OAUTH 2.0: 

La réponse acceptée ne fonctionne plus (erreur 401) .. Il y aura un problème d'authentification pour ce cas parce que FCM utilise maintenant OAUTH 2

J'ai donc lu la documentation de Firebase et, selon la documentation, le nouveau moyen de publier un message de données est;

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

En-têtes

Key: Content-Type, Value: application/json

Auth

Bearer YOUR_TOKEN 

Exemple de corps

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

L'URL contient l'ID de base de données que vous pouvez trouver sur votre console Firebase. (Aller aux réglages du projet)

Et maintenant prenons notre jeton (il ne sera valable que 1 heure):

Tout d’abord dans la console Firebase, ouvrez Paramètres> Comptes de service. Cliquez sur Générer une nouvelle clé privée pour stocker de manière sécurisée le fichier JSON contenant la clé. J'avais besoin de ce fichier JSON pour autoriser les requêtes du serveur manuellement. Je l'ai téléchargé.

Ensuite, je crée un projet node.js et utilise cette fonction pour obtenir mon jeton.

var PROJECT_ID = 'YOUR_PROJECT_ID';
var Host = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

Maintenant, je peux utiliser ce jeton dans ma demande de publication. Ensuite, je poste mon message de données, qui est maintenant géré par ma fonction onMessageReceived de apps.

0
Ozan

Depuis 2019, Google Firebase a un grand changement dans leurs API, je veux dire: 'com.google.firebase:firebase-messaging:18.0.0'

dans 18.0.0, ils ont supprimé MyFirebaseInstanceIDService et vous devez obtenir un jeton dans MyFirebaseMessagingService, il vous suffit d'écrire:

@Override
public void onNewToken(String token) {
    Log.d(TAG, "Refreshed token: " + token);

}

et aussi dans votre AndroidManifest.xml, vous devez supprimer:

<service Android:name=".service.MyFirebaseInstanceIDService">
        <intent-filter>
            <action Android:name="com.google.firebase.INSTANCE_ID_EVENT" />
        </intent-filter>
    </service>

En outre, il est recommandé de définir des valeurs par défaut pour personnaliser l'apparence des notifications. Vous pouvez spécifier une icône par défaut personnalisée et une couleur par défaut personnalisée qui sont appliquées chaque fois que des valeurs équivalentes ne sont pas définies dans la charge de notification.

Ajoutez ces lignes à l'intérieur de la balise d'application pour définir l'icône et la couleur personnalisées par défaut:

    <meta-data
        Android:name="com.google.firebase.messaging.default_notification_icon"
        Android:resource="@drawable/ic_notification" />

    <meta-data
        Android:name="com.google.firebase.messaging.default_notification_color"
        Android:resource="@color/colorAccent" />

    <meta-data
        Android:name="com.google.firebase.messaging.default_notification_channel_id"
        Android:value="@string/Push_channel" />

maintenant, pour gérer les messages de notification dans une application en arrière-plan, vous devez définir une intention dans votre première activité, même s'il s'agit de SplashScreen. Lorsque votre application est en arrière-plan, Android dirige les messages de notification vers la barre d'état système. Un utilisateur tapant sur la notification ouvre le lanceur d'applications par défaut.

par exemple, si votre Json ressemble à ceci:

 "data": {
"message": "2",
"title": "1",
"pushType" : "banner",
"bannerLink": "http://www.google.com",
"image" : "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"}

il vous suffit d'écrire une intention simple pour obtenir ces valeurs:

        Bundle extras = intent.getExtras();
        String bannerLink = extras.getString("bannerLink");
        ...
        String channelId = extras.getString("channelId");
0

En juillet 2019

Android compileSdkVersion 28, buildToolsVersion 28.0.3 et firebase-messaging: 19.0.1

Après de nombreuses heures de recherche parmi toutes les autres questions et réponses de StackOverflow et après avoir essayé d'innombrables solutions obsolètes, cette solution a réussi à afficher des notifications dans ces 3 scénarios:

- L'application est au premier plan:
la notification est reçue par la méthode onMessageReceived de la classe MyFirebaseMessagingService

- L'application a été supprimée (elle ne s'exécute pas en arrière-plan): la notification est automatiquement envoyée au plateau de notification par FCM. Lorsque l'utilisateur touche la notification, l'application est lancée en appelant l'activité qui a Android.intent.category.LAUNCHER dans le manifeste. Vous pouvez obtenir la partie données de la notification en utilisant getIntent (). GetExtras () à la méthode onCreate ().

- L'application est en arrière-plan: la notification est automatiquement envoyée au plateau de notification par FCM. Lorsque l'utilisateur touche la notification, l'application est mise au premier plan en lançant l'activité qui a Android.intent.category.LAUNCHER dans le manifeste. Comme mon application a launchMode = "singleTop" dans cette activité, la méthode onCreate () n'est pas appelée car une activité de la même classe est déjà créée. La méthode onNewIntent () de cette classe est appelée et vous obtenez la partie données de la notification il en utilisant intent.getExtras ().

Étapes: 1- Si vous définissez l'activité principale de votre application comme suit:

<activity
    Android:name=".MainActivity"
    Android:label="@string/app_name"
    Android:largeHeap="true"
    Android:screenOrientation="portrait"
    Android:launchMode="singleTop">
    <intent-filter>
        <action Android:name=".MainActivity" />
        <action Android:name="Android.intent.action.MAIN" />
        <category Android:name="Android.intent.category.LAUNCHER" />
        <category Android:name="Android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

2- ajoutez ces lignes à la méthode onCreate () de votre MainActivity.class

Intent i = getIntent();
Bundle extras = i.getExtras();
if (extras != null) {
    for (String key : extras.keySet()) {
        Object value = extras.get(key);
        Log.d(Application.APPTAG, "Extras received at onCreate:  Key: " + key + " Value: " + value);
    }
    String title = extras.getString("title");
    String message = extras.getString("body");
    if (message!=null && message.length()>0) {
        getIntent().removeExtra("body");
        showNotificationInADialog(title, message);
    }
}

et ces méthodes à la même MainActivity.class:

@Override
public void onNewIntent(Intent intent){
    //called when a new intent for this class is created.
    // The main case is when the app was in background, a notification arrives to the tray, and the user touches the notification

    super.onNewIntent(intent);

    Log.d(Application.APPTAG, "onNewIntent - starting");
    Bundle extras = intent.getExtras();
    if (extras != null) {
        for (String key : extras.keySet()) {
            Object value = extras.get(key);
            Log.d(Application.APPTAG, "Extras received at onNewIntent:  Key: " + key + " Value: " + value);
        }
        String title = extras.getString("title");
        String message = extras.getString("body");
        if (message!=null && message.length()>0) {
            getIntent().removeExtra("body");
            showNotificationInADialog(title, message);
        }
    }
}


private void showNotificationInADialog(String title, String message) {

    // show a dialog with the provided title and message
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message);
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();
}

3- Créez la classe MyFirebase comme ceci:

package com.yourcompany.app;

import Android.content.Intent;
import Android.util.Log;

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

public class MyFirebaseMessagingService extends FirebaseMessagingService {


    public MyFirebaseMessagingService() {
        super();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(Application.APPTAG, "myFirebaseMessagingService - onMessageReceived - message: " + remoteMessage);

        Intent dialogIntent = new Intent(this, NotificationActivity.class);
        dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        dialogIntent.putExtra("msg", remoteMessage);
        startActivity(dialogIntent);

    }

}

4- Créez une nouvelle classe NotificationActivity.class comme ceci:

package com.yourcompany.app;

import Android.app.Activity;
import Android.app.AlertDialog;
import Android.content.DialogInterface;
import Android.os.Bundle;
import Android.util.Log;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ContextThemeWrapper;

import com.google.firebase.messaging.RemoteMessage;

public class NotificationActivity extends AppCompatActivity {

private Activity context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = this;
    Bundle extras = getIntent().getExtras();

    Log.d(Application.APPTAG, "NotificationActivity - onCreate - extras: " + extras);

    if (extras == null) {
        context.finish();
        return;
    }

    RemoteMessage msg = (RemoteMessage) extras.get("msg");

    if (msg == null) {
        context.finish();
        return;
    }

    RemoteMessage.Notification notification = msg.getNotification();

    if (notification == null) {
        context.finish();
        return;
    }

    String dialogMessage;
    try {
        dialogMessage = notification.getBody();
    } catch (Exception e){
        context.finish();
        return;
    }
    String dialogTitle = notification.getTitle();
    if (dialogTitle == null || dialogTitle.length() == 0) {
        dialogTitle = "";
    }

    AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(context, R.style.myDialog));
    builder.setTitle(dialogTitle);
    builder.setMessage(dialogMessage);
    builder.setPositiveButton(getResources().getString(R.string.accept), new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.cancel();
        }
    });
    AlertDialog alert = builder.create();
    alert.show();

}

}

5- Ajoutez ces lignes à votre manifeste d'application, dans vos tags

    <service
        Android:name=".MyFirebaseMessagingService"
        Android:exported="false">
        <intent-filter>
            <action Android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

    <meta-data Android:name="com.google.firebase.messaging.default_notification_channel_id" Android:value="@string/default_notification_channel_id"/>

    <activity Android:name=".NotificationActivity"
        Android:theme="@style/myDialog"> </activity>

    <meta-data
        Android:name="com.google.firebase.messaging.default_notification_icon"
        Android:resource="@drawable/notification_icon"/>

    <meta-data
        Android:name="com.google.firebase.messaging.default_notification_color"
        Android:resource="@color/color_accent" />

6- Ajoutez ces lignes dans votre méthode Application.Java onCreate () ou dans la méthode MainActivity.class onCreate ():

      // notifications channel creation
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      // Create channel to show notifications.
      String channelId = getResources().getString("default_channel_id");
      String channelName = getResources().getString("General announcements");
      NotificationManager notificationManager = getSystemService(NotificationManager.class);
      notificationManager.createNotificationChannel(new NotificationChannel(channelId,
              channelName, NotificationManager.IMPORTANCE_LOW));
  }

Terminé.

Maintenant, pour que cela fonctionne bien dans les 3 scénarios mentionnés, vous devez envoyer la notification à partir de la console Web Firebase de la manière suivante:

Dans la section Notification: Titre de la notification = Titre à afficher dans la boîte de dialogue de notification (facultatif) Texte de la notification = Message à afficher à l'utilisateur (obligatoire) Puis dans la section Cible: App = votre Android app et en plus Section Options: Android Notification Channel = default_channel_id Clé Données personnalisées: valeur du titre: (même texte ici que dans le champ Titre de la section Notification) clé: valeur du corps: (même texte ici que dans le champ Message de la section Notification) clé: click_action valeur: .MainActivity Sound = Disabled
Expire = 4 semaines

Vous pouvez le déboguer dans l'émulateur avec l'API 28 avec Google Play.

Bonne codage!

0
alvaro

En utilisant ce code, vous pouvez obtenir la notification en arrière-plan/au premier plan et mettre aussi l'action

//Data should come in this format from the notification
{
  "to": "/xyz/Notifications",
  "data": {
      "key1": "title notification",
      "key2": "description notification"
  }
}

In-App utilise ce code:

  @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
      String key1Data = remoteMessage.getData().get("key1");
      // use key1Data to according to your need
    }
0
Ashish Kumar
  // Place this code on your MainActivity,then you will get your payload
  // Handle possible data accompanying notification message.
    // [START handle_data_extras]
    if (getIntent().getExtras() != null) {
        for (String key : getIntent().getExtras().keySet()) {
            Object value = getIntent().getExtras().get(key);
            Log.d(TAG, "Key: " + key + " Value: " + value);
        }
    }
0
baderkhane

En plus des réponses ci-dessus, Si vous testez les notifications Push à l’aide de Console FCM , la clé et l’objet 'data' sont pas ajoutés au groupe de notifications Push. Ainsi, vous ne recevrez pas de notification Push détaillée lorsque l'application est en arrière-plan ou tuée.

Dans ce cas, vous devez opter pour votre console d'administration principale pour tester le scénario d'arrière-plan de l'application.

Ici, vous aurez ajouté la clé 'data' à votre offre Push. donc, Push détaillé sera affiché comme prévu . Espérons que cela aide peu.

0
Max Droid