So behandeln Sie Benachrichtigungen, wenn sich die App im Hintergrund in Firebase befindet

425

Hier ist mein Manifest

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

Wenn sich die App im Hintergrund befindet und eine Benachrichtigung eintrifft, wird die Standardbenachrichtigung angezeigt und mein Code von wird nicht ausgeführt onMessageReceived.

Hier ist mein onMessageReceivedCode. Dies wird aufgerufen, wenn meine App im Vordergrund ausgeführt wird, nicht, wenn die App im Hintergrund ausgeführt wird. Wie führe ich diesen Code aus, wenn sich die App auch im Hintergrund befindet?

// [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]
Parth Patel
quelle
1
Es ist im Override-Beispiel von onMessageReceived () geschrieben , heißt es in der zweiten Kommentarzeile Not getting messages here? See why this may be: goo.gl/39bRNJ . Die Lösung, wie die folgenden Antworten, finden Sie in der Dokumentation in Nachrichten mit Benachrichtigung und Datennutzdaten
fllo
Kurz gesagt, um Ihre getötete App zu aktivieren, sollten Sie immer eine Benachrichtigung mit Datenobjekt senden, um Ihren Benachrichtigungsdienst-Klassenhandler FirebaseMessagingService.onMessageReceived () in Ihrer Anwendung aufzurufen. Versuchen Sie auch, es nicht von der Firebase-Konsole aus zu senden, sondern von einem anderen Ort aus (z. B. Online-Testpostdienst).
Zon
1
Diese Lösung hat bei mir funktioniert stackoverflow.com/a/44150822/6632278 Hoffnung hilft. Viel Glück
Tony Barajas
was ".fcm." PshycoFirebaseMessagingServices ist in Ihrem Manifest? Ich bekomme Fehler der Klasse nicht gefunden .. und habe nirgendwo gefunden, was dieser erste Teil des Parameters ist.
Éder Rocha Bezerra

Antworten:

660

1. Warum passiert das?

In FCM (Firebase Cloud Messaging) gibt es zwei Arten von Nachrichten:

  1. Nachrichten anzeigen : Diese Nachrichten lösen den onMessageReceived()Rückruf nur aus, wenn sich Ihre App im Vordergrund befindet
  2. Datennachrichten : Diese Nachrichten lösen den onMessageReceived()Rückruf aus, auch wenn sich Ihre App im Vordergrund / Hintergrund / getötet befindet

HINWEIS: Das Firebase-Team hat noch keine Benutzeroberfläche zum Senden data-messagesan Ihre Geräte entwickelt. Sie sollten Ihren Server zum Senden dieses Typs verwenden!



2. Wie geht das?

Um dies zu erreichen, müssen Sie eine POSTAnfrage an die folgende URL senden:

POST https://fcm.googleapis.com/fcm/send

Überschriften

  • Schlüssel : Content-Type , Wert: application/json
  • Schlüssel : Authorization , Wert: key=<your-server-key>

Körper mit Themen

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

Oder wenn Sie es an bestimmte Geräte senden möchten

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


HINWEIS: Stellen Sie sicher, dass Sie keinen JSON-Schlüssel hinzufügen. notification
HINWEIS: Um Ihren Serverschlüssel zu erhalten, finden Sie ihn in der Firebase-Konsole:Your project -> settings -> Project settings -> Cloud messaging -> Server Key

3. Wie gehe ich mit der Push-Benachrichtigung um?

So gehen Sie mit der empfangenen Nachricht um:

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

     // Manage data
}
Antonio
quelle
4
Sie können "Daten" - und "Benachrichtigungs" -Schlüssel in derselben Benachrichtigung senden, indem Sie die folgenden Schritte ausführen : stackoverflow.com/a/42279260/2734021 :)
Daniel S.
15
Firebase team have not developed a UI to send data-messages to your devices, yet.Hat sich das im letzten Jahr geändert?
Hankrecords
2
@Antonio In oreo wird onMessageReceived nicht aufgerufen, wenn die App beendet wird. Ich habe nur Nutzdaten mit Daten. Hast du ein Update?
Samir Mangroliya
63
Wenn die App im Hintergrund ist, wird onMessageReceivedsie nicht aufgerufen und es ist ein ernstes Problem in FCM !!! Bitte aktualisieren Sie auch Ihre Antwort.
Muhammad Babar
2
Nun, für mich scheint es, dass dies auf bestimmten Android-Geräten passiert. Verbrachte Stunden damit zu denken, dass es ein tatsächliches Problem war, stellte sich dann aber als nichts heraus. Mein Rat ist also, es auf verschiedenen Geräten zu testen. Ich habe es sogar auf einer VM getestet und die Benachrichtigung auch dann erhalten, wenn die App beendet wurde. Ich sage das nur, um jemandem Zeit zu sparen.
Tarek-Dev
158

Damit die Firebase-Bibliothek in den folgenden Fällen Ihre onMessageReceived () aufruft

  1. App im Vordergrund
  2. App im Hintergrund
  3. App wurde getötet

Sie dürfen den JSON-Schlüssel "Benachrichtigung" nicht in Ihre Anfrage an die Firebase-API einfügen, sondern müssen stattdessen "Daten" verwenden (siehe unten).

Die folgende Nachricht ruft Ihr onMessageReceived () nicht auf, wenn sich Ihre App im Hintergrund befindet oder beendet wurde, und Sie können Ihre Benachrichtigung nicht anpassen.

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

aber stattdessen wird dies funktionieren

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

Grundsätzlich wird die Nachricht im Argument RemoteMessage zusammen mit Ihrem Datenobjekt als Map gesendet. Anschließend können Sie die Benachrichtigung in onMessageReceived wie im Snippet hier verwalten

@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
    */
}
Teerakiat Chitawattanarat
quelle
1
Ist dies über die Firebase-Konsole möglich?
Koder
@koder, die Firebase-Konsole unterstützt dies leider nicht. Sie müssen das Tool verwenden, um eine Post-Message-Anfrage an Firebase zu senden, z. B. Curl oder Postman (Chrome-Plugin). Die Firebase-Messaging-API finden Sie im Dokument hier - firebase.google.com/docs / Cloud-Messaging / http-Server-Ref
Teerakiat Chitawattanarat
1
das ist es, wonach ich mehr als einen Tag gesucht habe ..... Vielen Dank, es hat perfekt funktioniert. und es wäre besser, wenn Sie erklären, wie die Schlüssel-Tal-Paare in den Daten in onMessageReceived () behandelt werden können, um eine Aktivität mit diesen Werten zu starten.
Boopathi T
25
Ihre Methode funktioniert gut, wenn die App im Hintergrund ist, aber wenn die App beendet wird,
erhalte
8
Gleiches Problem von Sanzhar. Wenn die App getötet wird, erhalte ich keine Nachricht.
Giacomo M
104

Ich habe das Gefühl, dass alle Antworten unvollständig sind, aber alle haben etwas, das Sie benötigen, um eine Benachrichtigung mit Daten zu verarbeiten, wenn sich Ihre App im Hintergrund befindet.

Befolgen Sie diese Schritte und Sie können Ihre Benachrichtigungen verarbeiten, wenn sich Ihre App im Hintergrund befindet.

1. Fügen Sie einen Intent-Filter wie folgt hinzu:

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

zu einer Aktivität, die Sie die Benachrichtigungsdaten verarbeiten möchten.

  1. Senden Sie Benachrichtigungen mit dem nächsten Format:

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

Der Schlüssel hier ist hinzufügen

"click_action" : ".MainActivity"

Dabei ist .MainActivity die Aktivität mit dem Intent-Filter, den Sie in Schritt 1 hinzugefügt haben.

  1. Erhalten Sie "Daten" -Informationen aus der Benachrichtigung im onCreate von ".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
        }
    }

Und das sollte alles sein, was Sie tun müssen. Ich hoffe das hilft jemandem :)

Daniel S.
quelle
5
Dies sollte die richtige Antwort sein. Keines der Dokumente sagt etwas darüber aus, dass eine click_action UND ein Intent Filter erforderlich sind, damit die Benachrichtigung überhaupt in der Taskleiste angezeigt wird. Sie sind beide erforderlich.
Airowe
@airowe sie sind nicht erforderlich, damit die Benachrichtigung
angezeigt wird
Ich habe sowohl Daten- als auch Benachrichtigungsblöcke, kann aber keine Daten in Aktivität empfangen.
Ashwani
3
Ich verstehe nur nicht, dass dies nicht die akzeptierte Antwort ist. Ohne click_action funktioniert es einfach nicht. Rettete meinen Tag
Arun Shankar
4
Vielen Dank für Ihre Unterstützung @ArunShankar. Die akzeptierte Antwort wurde 7 Monate vor meiner beantwortet und ist eine gute Antwort. Ich kann nicht verstehen, warum niemand über click_action spricht und deshalb habe ich meine Antwort hinzugefügt. Ich bin sehr froh, dass es für viele Menschen sehr nützlich ist und das ist es, was am Ende des Tages zählt :)
Daniel S.
42

Gemäß der Firebase-Dokumentation in Send Downstream mit Firebase gibt es zwei Arten von Nutzdaten:

  1. Daten

    Dieser Parameter gibt die benutzerdefinierten Schlüssel-Wert-Paare der Nutzdaten der Nachricht an. Die Client-App ist für die Verarbeitung von Datennachrichten verantwortlich. Datennachrichten haben nur benutzerdefinierte Schlüssel-Wert-Paare.

  2. Benachrichtigung

    Dieser Parameter gibt die vordefinierten, vom Benutzer sichtbaren Schlüssel-Wert-Paare der Benachrichtigungsnutzdaten an. FCM zeigt die Nachricht automatisch Endbenutzergeräten im Namen der Client-App an. Benachrichtigungsnachrichten verfügen über einen vordefinierten Satz von vom Benutzer sichtbaren Schlüsseln.

Wenn Sie im Vordergrund stehen, können Sie die Daten in FCM mit onMessageReceived () abrufen . Sie können Ihre Daten aus Datennutzdaten abrufen .

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

Wenn Sie sich im Hintergrund befinden, zeigt FCM eine Benachrichtigung in der Taskleiste basierend auf den Informationen aus der Benachrichtigungsnutzlast an . Titel, Nachricht und Symbol, die für die Benachrichtigung in der Taskleiste verwendet werden, werden von der Benachrichtigungsnutzlast abgerufen .

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

Diese Benachrichtigungsnutzdaten werden verwendet, wenn Sie Benachrichtigungen automatisch in der Taskleiste anzeigen möchten, wenn sich Ihre App im Hintergrund befindet. Um Benachrichtigungsdaten zu erhalten, wenn sich Ihre App im Hintergrund befindet, sollten Sie click_action in die Benachrichtigungsnutzdaten einfügen .

Wenn Sie Ihre App öffnen und eine bestimmte Aktion ausführen möchten (im Hintergrund), setzen Sie click_action in der Benachrichtigungsnutzlast und ordnen Sie sie einem Absichtsfilter in der Aktivität zu, die Sie starten möchten. Setzen Sie beispielsweise click_action auf OPEN_ACTIVITY_1, um einen Absichtsfilter wie den folgenden auszulösen:

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

Fügen Sie diesen Absichtsfilter in Ihrem Manifest in einem Ihrer Aktivitäts-Tags ein. Wenn Sie auf die Benachrichtigung klicken, wird die App geöffnet und Sie gelangen direkt zu der Aktivität, die Sie in click_action definiert haben, in diesem Fall "OPEN_ACTIVTY_1". Und innerhalb dieser Aktivität können Sie die Daten erhalten durch:

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

Ich verwende FCM für meine Android-App und verwende beide Nutzdaten. Hier ist das Beispiel von JSON, das ich verwende:

{
  "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"
   }
}
Hendy Evan
quelle
"Fügen Sie diesen Absichtsfilter in Ihr Manifest innerhalb des Anwendungs-Tags ein." Sie können den Intent-Filter nicht in das Anwendungs-Tag einfügen.
Kyrylo Zapylaiev
Ihre JSON-Daten zeigen nicht an, wohin der click_action-Schlüssel führt.
Josh
das ist nicht die richtige antwort? Was ist eine Klickaktion und wohin geht sie? jemand sollte abstimmen oder dies säubern
rana
1
@KyryloZapylaiev Ich korrigiere und aktualisiere gerade die Antwort: "Setze diesen Absichtsfilter in dein Manifest, in eines deiner Aktivitäts-Tags".
Dika
1
@ Josh aktualisiert und formatiert. Sie können es erneut überprüfen
Dika
32

Laut docs

Behandeln Sie Nachrichten in einer Hintergrund-App

Wenn sich Ihre App im Hintergrund befindet, leitet Android Benachrichtigungsnachrichten an die Taskleiste weiter. Ein Benutzer, der auf die Benachrichtigung tippt, öffnet standardmäßig den App-Starter.

Dies schließt Nachrichten ein, die sowohl Benachrichtigungen als auch Datennutzdaten enthalten. In diesen Fällen wird die Benachrichtigung an die Taskleiste des Geräts gesendet, und die Datennutzlast wird in den Extras der Absicht Ihrer Starteraktivität geliefert.

Wenn Sie Ihre App öffnen und eine bestimmte Aktion ausführen möchten, setzen Sie click_action in der Benachrichtigungsnutzlast und ordnen Sie sie einem Absichtsfilter in der Aktivität zu, die Sie starten möchten. Setzen Sie beispielsweise click_action auf OPEN_ACTIVITY_1, um einen Absichtsfilter wie den folgenden auszulösen:

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

Bearbeiten:

Basierend auf diesem Thread :

Sie können die Nutzdaten von click_action nicht mit Firebase Console festlegen. Sie können versuchen, mit einem Curl-Befehl oder einem benutzerdefinierten http-Server zu testen

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\"}}"
Shubhank
quelle
1
Du hast recht. Ich habe die Dokumente gelesen. aber ich bin verwirrt, wo ich das in mein Manifest setzen soll? Ich muss den Code auf der onMessageReceived in dieser Java-Datei ausführen. Was muss ich dafür tun, Sir?
Parth Patel
Sie können die App nicht automatisch onMessageReveiced aufrufen lassen, wenn sie sich im Hintergrund befindet. Stattdessen müssen Sie die empfangene Absicht behandeln und den Handler dazu bringen, sie aufzurufen. Oder wahrscheinlich ist es am besten, eine separate Klasse / Methode zu implementieren, die sowohl von onMessageReveiced als auch von Ihrer Absichtsbehandlung aufgerufen wird. Ich habe onNewIntent der Hauptaktivität einen Handler hinzugefügt, der für mich einwandfrei funktioniert.
Diidu
Es ist zu spät, um auf @ Parath Patel-Fragen zu antworten, aber vielleicht hilft dies jemand anderem mit den gleichen Problemen. Schauen Sie sich meine Antwort hier an. stackoverflow.com/a/42279260/2734021
Daniel S.
Wo musste diese Aktion durchgeführt werden? für meine Aktivität oder Firebasemessage Service?
Mahdi
** Bei mehrfacher Benachrichtigung funktioniert die Umleitung nicht? Beispiel: Wenn ich drei Benachrichtigungen von fcm im Hintergrund mit "click_action" habe, wird zuerst die Benachrichtigung erfolgreich umgeleitet und dann 2 Benachrichtigungen. Die Aktivitätsumleitung funktioniert nicht
prasanthMurugan
24

Arbeiten ab Juli 2019

Android compileSdkVersion 28, buildToolsVersion 28.0.3 und Firebase-Messaging: 19.0.1

Nach vielen, vielen Stunden Recherche durch alle anderen Fragen und Antworten von StackOverflow und dem Versuch unzähliger veralteter Lösungen gelang es dieser Lösung, Benachrichtigungen in diesen drei Szenarien anzuzeigen:

- App steht im Vordergrund:
Die Benachrichtigung wird von der onMessageReceived-Methode in meiner MyFirebaseMessagingService-Klasse empfangen

- Die App wurde beendet (sie wird nicht im Hintergrund ausgeführt): Die Benachrichtigung wird von FCM automatisch an die Benachrichtigungsleiste gesendet. Wenn der Benutzer die Benachrichtigung berührt, wird die App gestartet, indem die Aktivität aufgerufen wird, deren Manifest android.intent.category.LAUNCHER enthält. Sie können den Datenteil der Benachrichtigung mit getIntent (). GetExtras () in der onCreate () -Methode abrufen.

- App befindet sich im Hintergrund: Die Benachrichtigung wird von FCM automatisch an die Benachrichtigungsleiste gesendet. Wenn der Benutzer die Benachrichtigung berührt, wird die App in den Vordergrund gestellt, indem die Aktivität gestartet wird, deren Manifest android.intent.category.LAUNCHER enthält. Da meine App in dieser Aktivität launchMode = "singleTop" hat, wird die onCreate () -Methode nicht aufgerufen, da bereits eine Aktivität derselben Klasse erstellt wurde. Stattdessen wird die onNewIntent () -Methode dieser Klasse aufgerufen und Sie erhalten den Datenteil von die Benachrichtigung dort mit intent.getExtras ().

Schritte: 1- Wenn Sie die Hauptaktivität Ihrer App folgendermaßen definieren:

<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- Fügen Sie diese Zeilen in der onCreate () -Methode Ihrer MainActivity.class hinzu

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

und diese Methoden zu derselben 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- Erstellen Sie die Klasse MyFirebase wie folgt:

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- Erstellen Sie eine neue Klasse NotificationActivity.class wie folgt:

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- Fügen Sie diese Zeilen zu Ihrem App-Manifest in Ihren Tags hinzu

    <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- Fügen Sie diese Zeilen in Ihre Application.java onCreate () -Methode oder in die MainActivity.class onCreate () -Methode ein:

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

Erledigt.

Damit dies in den drei genannten Szenarien gut funktioniert, müssen Sie die Benachrichtigung wie folgt von der Firebase-Webkonsole senden:

Im Abschnitt Benachrichtigung: Benachrichtigungstitel = Titel, der im Benachrichtigungsdialog angezeigt werden soll (optional) Benachrichtigungstext = Nachricht, die dem Benutzer angezeigt werden soll (erforderlich) Dann im Abschnitt Ziel: App = Ihre Android-App und im Abschnitt Zusätzliche Optionen: Android-Benachrichtigungskanal = default_channel_id Benutzerdefinierter Datenschlüssel: Titelwert: (gleicher Text hier als im Feld Titel des Benachrichtigungsabschnitts) Schlüssel: Textwert: (gleicher Text hier als im Nachrichtenfeld des Benachrichtigungsabschnitts) Schlüssel: click_action-Wert: .MainActivity Sound = Deaktiviert
läuft ab = 4 Wochen

Sie können es im Emulator mit API 28 mit Google Play debuggen.

Viel Spaß beim Codieren!

Alvaro
quelle
2
Vielen Dank für diese tolle Antwort.
Alex Chengalan
@alvaro, Wenn ich Url öffnen möchte, wenn ich eine Benachrichtigung erhalte, wie ich damit
umgehen
funktioniert nicht in vivo opp Telefon, wenn App geschlossen oder getötet wird
Android Developer
Ich habe es noch nicht in einem Vivo-Telefon versucht, aber es funktioniert derzeit in vielen anderen Android-Telefonen. Bitte lesen Sie jeden Schritt langsam durch, überprüfen Sie alle Details und aktivieren Sie dann das Debuggen von Haltepunkten in der ersten Zeile jeder der hier genannten Methoden. Schließen Sie ein echtes Telefon mit einem Kabel an Ihren Entwicklungscomputer an und debuggen Sie die App beim Senden eine Nachricht von FCM. Überprüfen Sie, ob Sie die FCM-Nachrichten mit allen von mir erwähnten Parametern und dem Format senden. Viel Glück!
Alvaro
2
Dies ist die aktuellste Antwort, da in der Firebase-Dokumentation jetzt lautet: Wenn sich Ihre App im Hintergrund befindet, leitet Android Benachrichtigungsnachrichten an die Taskleiste weiter. Ein Benutzer, der auf die Benachrichtigung tippt, öffnet standardmäßig den App-Starter. Dies schließt Nachrichten ein, die sowohl Benachrichtigungen als auch Datennutzdaten enthalten. In diesen Fällen wird die Benachrichtigung an die Taskleiste des Geräts gesendet, und die Datennutzlast wird in den Extras der Absicht Ihrer Starteraktivität geliefert. ( firebase.google.com/docs/cloud-messaging/android/… ) So viele alte Antworten sind veraltet
Riot Goes Woof
20

Da die display-messagesvon Firebase Notification UI gesendeten Funktionen nur funktionieren, wenn sich Ihre App im Vordergrund befindet. Denn data-messagesgibt es eine Notwendigkeit , einen POST Aufruf zu machen FCM

Schritte

  1. Installieren Sie die Google Chrome-Erweiterung des Advanced Rest Client Geben Sie hier die Bildbeschreibung ein

  2. Fügen Sie die folgenden Überschriften hinzu

    Schlüssel : Inhaltstyp, Wert : application / json

    Schlüssel : Autorisierung, Wert : Schlüssel = "Ihr Serverschlüssel" Geben Sie hier die Bildbeschreibung ein

  3. Fügen Sie den Körper hinzu

    • Bei Verwendung von Themen:

      {
          "to" : "/topics/topic_name",
          "data": {
          "key1" : "value1",
          "key2" : "value2",
          }
      }
    • Bei Verwendung der Registrierungs-ID:

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

Das ist es!. Hören Sie sich jetzt onMessageReceivedwie gewohnt den Rückruf an.

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

Um die Nachricht im Hintergrund zu erfassen, müssen Sie a verwenden BroadcastReceiver

import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.legacy.content.WakefulBroadcastReceiver
import com.google.firebase.messaging.RemoteMessage

class FirebaseBroadcastReceiver : WakefulBroadcastReceiver() {

    val TAG: String = FirebaseBroadcastReceiver::class.java.simpleName

    override fun onReceive(context: Context, intent: Intent) {

        val dataBundle = intent.extras
        if (dataBundle != null)
            for (key in dataBundle.keySet()) {
                Log.d(TAG, "dataBundle: " + key + " : " + dataBundle.get(key))
            }
        val remoteMessage = RemoteMessage(dataBundle)
        }
    }

und füge dies deinem Manifest hinzu:

<receiver
      android:name="MY_PACKAGE_NAME.FirebaseBroadcastReceiver"
      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>
Romulano
quelle
7
Dies erhält wirklich die Benachrichtigung, wenn sich die App im Hintergrund befindet. Der Standard-Firebase-Empfänger wird jedoch nicht daran gehindert, damit umzugehen, sodass die Nachricht weiterhin als Benachrichtigung angezeigt wird.
Galya
Im Moment funktioniert es nicht, deshalb schlage ich diese Lösung vor. Es gibt einen Fehler in der Google-Bugbase. Vielleicht möchten Sie das überprüfen.
Romulano
Könnten Sie bitte einen Link zum Fehler hier posten
Galya
Wie erhalte ich Daten aus der Benachrichtigung?
Ravi Vaghela
Dies funktioniert eindeutig nicht, wenn die App beendet wird. Ich habe diese Lösung stundenlang ausprobiert. Aus irgendeinem Grund arbeitet der Empfänger, während sich die App im Hintergrund befindet, und funktioniert nicht, wenn die App beendet wird
XcodeNOOB
16
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

}

wird nicht jedes Mal aufgerufen, wenn es nur aufgerufen wird, wenn sich die App im Vordergrund befindet

Es gibt eine Überschreibungsmethode, die jedes Mal aufgerufen wird, unabhängig davon, welche App im Vordergrund oder im Hintergrund steht oder getötet wurde. Diese Methode ist jedoch mit dieser Firebase-API-Version verfügbar

Dies ist die Version, die Sie aus Gradle importieren müssen

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

Das ist die Methode

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

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


}

Mit der vorherigen Firebase-API war diese Methode nicht vorhanden. In diesem Fall behandelt sich die Fire Base selbst, wenn sich die App im Hintergrund befindet. Jetzt haben Sie diese Methode, was auch immer Sie tun möchten. Sie können sie hier in dieser Methode ausführen. ...

Wenn Sie eine frühere Version als die Standardaktivität verwenden, wird in diesem Fall die Daten auf dieselbe Weise abgerufen

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

// Mach was du willst .... }

Im Allgemeinen ist dies die Struktur vom Server, die wir in der Benachrichtigung erhalten

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

Es liegt an dir, wie du diesen Datenschlüssel geben willst oder wie du alles benachrichtigen willst, was du geben kannst ....... was auch immer du hier mit demselben Schlüssel geben willst, du wirst diese Daten erhalten ........ .

Es gibt nur wenige Fälle, in denen Sie in diesem Fall keine Klickaktion senden, wenn Sie auf Benachrichtigung klicken. Die Standardaktivität wird geöffnet. Wenn Sie jedoch Ihre spezifische Aktivität öffnen möchten, wenn sich die App im Hintergrund befindet, können Sie Ihre Aktivität von dieser Methode auf handleIntent aus aufrufen wird jedes Mal aufgerufen

Avinash Jadaun
quelle
Ich habe das Firebase-Messaging auf 10.2.1 aktualisiert, der Benachrichtigungsnachricht Daten hinzugefügt und es hat funktioniert. Vordergrund, Hintergrund und getötet. Vielen Dank
Firas Shrourou
In Kotlin erhalte ich den folgenden Fehler: (44, 5) 'handleIntent' in 'FirebaseMessagingService' ist endgültig und kann nicht überschrieben werden
ugali soft
Es funktioniert nicht über den Versionen von Firebase 11
venu46
14

Laut Dokumentation: 17. Mai 2017

Wenn sich Ihre App im Hintergrund befindet , leitet Android Benachrichtigungsnachrichten an die Taskleiste weiter. Ein Benutzer, der auf die Benachrichtigung tippt, öffnet standardmäßig den App-Starter .

Dies umfasst Nachrichten, die sowohl Benachrichtigungs- als auch Datennutzdaten enthalten (und alle von der Benachrichtigungskonsole gesendeten Nachrichten). In diesen Fällen wird die Benachrichtigung an die Taskleiste des Geräts gesendet, und die Datennutzlast wird in den Extras der Absicht Ihrer Starteraktivität geliefert.

Sie sollten also beide Nutzlastbenachrichtigungen + Daten verwenden:

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

Es ist nicht erforderlich, click_action zu verwenden. Sie sollten nur Exras aus der Absicht der LAUNCHER-Aktivität erhalten

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

Java-Code sollte in der onCreate-Methode in MainActivity enthalten sein:

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

Sie können beide Nutzlastbenachrichtigungen + Daten in der Firebase Notifications Console testen . Vergessen Sie nicht, benutzerdefinierte Datenfelder im Abschnitt Erweiterte Optionen auszufüllen

Mihuilk
quelle
13

Hier finden Sie klarere Konzepte zur Firebase-Nachricht. Ich habe es von ihrem Support-Team gefunden.

Firebase hat drei Nachrichtentypen :

Benachrichtigungsnachrichten : Die Benachrichtigungsnachricht funktioniert im Hintergrund oder im Vordergrund. Wenn sich die App im Hintergrund befindet, werden Benachrichtigungsnachrichten an die Taskleiste gesendet. Wenn sich die App im Vordergrund befindet, werden Nachrichten von onMessageReceived()oder didReceiveRemoteNotificationRückrufe verarbeitet. Dies sind im Wesentlichen sogenannte Display-Nachrichten.

Datennachrichten : Auf der Android-Plattform können Datennachrichten im Hintergrund und im Vordergrund ausgeführt werden. Die Datennachricht wird von onMessageReceived () verarbeitet. Ein plattformspezifischer Hinweis wäre hier: Unter Android kann die Datennutzlast in der Absicht abgerufen werden, die zum Starten Ihrer Aktivität verwendet wird. Um dies zu erläutern, "click_action":"launch_Activity_1"können Sie diese Absicht getIntent()nur von abrufen Activity_1.

Nachrichten mit Benachrichtigungs- und Datennutzdaten : Im Hintergrund empfangen Apps die Benachrichtigungsnutzdaten in der Benachrichtigungsleiste und verarbeiten die Datennutzdaten nur, wenn der Benutzer auf die Benachrichtigung tippt. Im Vordergrund empfängt Ihre App ein Nachrichtenobjekt mit beiden verfügbaren Nutzdaten. Zweitens wird der click_actionParameter häufig in Benachrichtigungsnutzdaten und nicht in Datennutzdaten verwendet. Bei Verwendung innerhalb der Datennutzlast wird dieser Parameter als benutzerdefiniertes Schlüssel-Wert-Paar behandelt. Daher müssen Sie eine benutzerdefinierte Logik implementieren, damit er wie beabsichtigt funktioniert.

Außerdem empfehle ich Ihnen, die onMessageReceivedMethode (siehe Datennachricht) zu verwenden, um das Datenpaket zu extrahieren. Nach Ihrer Logik habe ich das Bundle-Objekt überprüft und den erwarteten Dateninhalt nicht gefunden. Hier ist ein Verweis auf einen ähnlichen Fall, der mehr Klarheit bieten könnte.

Für weitere Informationen besuchen Sie meinen diesen Thread

Md. Sajedul Karim
quelle
8

Einfache Zusammenfassung wie diese

  • wenn Ihre App ausgeführt wird;

    onMessageReceived()

ist Auslöser.

  • wenn Ihre App nicht ausgeführt wird (durch Wischen getötet);

    onMessageReceived()

wird nicht direkt ausgelöst und geliefert. Wenn Sie ein spezielles Schlüssel-Wert-Paar haben. Sie funktionieren nicht, weil onMessageReceived () nicht funktioniert.

Ich habe diesen Weg gefunden;

Setzen Sie in Ihre Launcher-Aktivität diese Logik ein:

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

Suchen Sie in diesem if-Block nach Ihren Schlüsseln gemäß der Firebase-Benutzeroberfläche.

In diesem Beispiel mein Schlüssel und Wert wie oben; (Entschuldigung für die Sprache =)) Geben Sie hier die Bildbeschreibung ein

Wenn mein Code funktioniert, erhalte ich "com.rda.note".

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

Mit dieser Codezeile habe ich meine Anwendung geschlossen und Google Play Market geöffnet

Happy Coding =)

Arda
quelle
6

Ich habe die Szenarien herausgefunden,

Wenn sich die App im Vordergrund befindet , wird die Methode onMessageReceived () vom FirebaseService aufgerufen. Daher wird der in der Serviceklasse definierte pendingIntent aufgerufen.

Und wenn sich die App im Hintergrund befindet , wird die erste Aktivität aufgerufen.

Wenn Sie nun eine Splash-Aktivität verwenden , müssen Sie berücksichtigen, dass die Splash-Aktivität aufgerufen wird. Wenn keine Splash-Aktivität vorhanden ist, wird unabhängig von der ersten Aktivität aufgerufen.

Dann müssen Sie getIntent () der firstActivity überprüfen, um festzustellen , ob ein Bundle vorhanden ist. Wenn alles in Ordnung ist, wird das Bundle mit den eingegebenen Werten angezeigt. Wenn der Wert im vom Server gesendeten Daten-Tag so aussieht,

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

Dann werden Sie in der ersten Aktivität sehen, dass es eine gültige Absicht gibt ( getIntent () ist nicht null ), ein gültiges Bundle und innerhalb des Bundles den gesamten oben erwähnten JSON mit Daten als Schlüssel .

In diesem Szenario sieht der Code zum Extrahieren des Werts folgendermaßen aus:

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


            }
        }
Shamsul Arefin Sajib
quelle
3

Vielen Dank an Sie alle für Ihre Antworten. Aber ich habe dieses Problem gelöst, indem ich eine Datennachricht gesendet habe, anstatt eine Benachrichtigung zu senden . Servercode

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

?>

Und die Daten in onMessageReceived abgefangen

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());
}
}
Android Sanaullah
quelle
1
funktioniert es auch mit einem Hintergrund?
Tabish Khan
@ Tabishkhan Ja Bruder, es funktioniert, wenn Sie ein Problem haben, zögern Sie nicht, mich zu fragen .. danke
Android Sanaullah
1
Hallo @AndroidSanaullah, können Sie dem ersten Teil den Servercode erklären, wo setzen Sie ihn tatsächlich ein? Ich stehe vor dem gleichen Problem, aber ich verstehe den Serverteil nicht ganz. Verwenden Sie Postboten?
Shid
Curl wird für die Anfrage verwendet und alle Parameter werden an sie übergeben. @ Shid
Android Sanaullah
2

Entfernen Sie die Benachrichtigungsnutzdaten vollständig von Ihrer Serveranforderung. Senden Sie nur Daten und verarbeiten Sie sie onMessageReceived(), andernfalls werden Sie onMessageReceivednicht ausgelöst, wenn sich die App im Hintergrund befindet oder beendet ist.

Folgendes sende ich vom Server:

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

So können Sie Ihre Daten folgendermaßen empfangen onMessageReceived(RemoteMessage message): (Nehmen wir an, ich muss die ID erhalten)

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

Ebenso können Sie alle Daten abrufen, die Sie vom Server innerhalb gesendet haben onMessageReceived().

Zohab Ali
quelle
2

Der einfache Weg, Nachrichten zu senden, selbst wenn sich die App im Hintergrund und im Vordergrund befindet, ist wie folgt: - Um eine Nachricht über die API zu senden, können Sie ein Tool namens AdvancedREST Client verwenden, eine Chrome-Erweiterung, und eine Nachricht mit den folgenden Parametern senden.

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

Verwenden Sie diese URL: - https://fcm.googleapis.com/fcm/send Inhaltstyp: application / json Autorisierung: key = Ihr Serverschlüssel From oder Authoization key (siehe unten ref)

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

Den Autorisierungsschlüssel erhalten Sie, indem Sie die Google-Entwicklerkonsole besuchen und im linken Menü Ihres Projekts auf die Schaltfläche Anmeldeinformationen klicken. Unter den aufgeführten API-Schlüsseln ist der Serverschlüssel Ihr Autorisierungsschlüssel.

Und Sie müssen die Token-ID des Empfängers in den Abschnitt "bis" Ihrer POST-Anfrage einfügen, die über die API gesendet wird.

Syed Danish Haider
quelle
2

Wenn Sie an MessageReceived (RemoteMessage remoteMessage) im Hintergrund arbeiten möchten, senden Sie nur den Datenteil-Benachrichtigungsteil:

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

"AnotherActivity": "True", "to": "Geräte-ID oder Geräte-Token"

Auf diese Weise ist onMessageRecivied der Hintergrund und der Vordergrund eines Anrufs, ohne dass eine Benachrichtigung über die Benachrichtigungsleiste in Ihrer Launcher-Aktivität verarbeitet werden muss. Behandeln Sie die Datennutzdaten folgendermaßen:

  public void onMessageReceived(RemoteMessage remoteMessage)
    if (remoteMessage.getData().size() > 0) 
    Log.d(TAG, "Message data payload: " + remoteMessage.getData());      
user3385125
quelle
1

Juni 2018 Antwort -

Sie müssen sicherstellen, dass die Nachricht kein Schlüsselwort "Benachrichtigung" enthält. Geben Sie nur "Daten" an, und die App kann die Nachricht in onMessageReceived verarbeiten, auch wenn sie im Hintergrund oder getötet ist.

Verwenden von Cloud-Funktionen:

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

Dann in Ihrem onMessageReceived (), in Ihrer Klasse, die com.google.firebase.messaging.FirebaseMessagingService erweitert:

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.
Jeff Padgett
quelle
Haben Sie eine Quelle, ist es sicher?
Yogesh Rathi
Es ist sicher, ich benutze es in meinen Apps. 6 Monate nach dem Posten kann ich mich jedoch nicht an die Quelle erinnern - ich stelle mir vor, es ist die Firebase-Dokumentation.
Jeff Padgett
1

Laut OAUTH 2.0:

In diesem Fall tritt ein Auth-Problem auf, da FCM jetzt OAUTH 2 verwendet

Also habe ich die Firebase-Dokumentation gelesen und laut Dokumentation gibt es eine neue Möglichkeit, Datennachrichten zu veröffentlichen.

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

Überschriften

Key: Content-Type, Value: application/json

Auth

Bearer YOUR_TOKEN 

Beispielkörper

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

In der URL befindet sich die Datenbank-ID, die Sie auf Ihrer Firebase-Konsole finden. (Go Projekteinstellungen)

Und jetzt nehmen wir unser Token (es wird nur 1 Stunde gültig sein):

Öffnen Sie zunächst in der Firebase-Konsole Einstellungen> Dienstkonten . Klicken Sie auf Neuen privaten Schlüssel generieren , und speichern Sie die JSON-Datei mit dem Schlüssel sicher. Ich brauchte diese JSON-Datei, um Serveranforderungen manuell zu autorisieren. Ich habe es heruntergeladen.

Dann erstelle ich ein node.js-Projekt und verwende diese Funktion, um mein Token abzurufen.

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

Jetzt kann ich dieses Token in meiner Post-Anfrage verwenden. Dann poste ich meine Datennachricht und sie wird jetzt von meiner Apps onMessageReceived-Funktion verarbeitet.

Ozan
quelle
Akzeptierte Antwort funktioniert, Barer Token Auth ist nicht der richtige Weg. Sie müssen dies lesen, um es mit Postman zu versuchen: stackoverflow.com/questions/45309674/…
Carlos Jesus Arancibia Taborga
1

Seit 2019 hat Google Firebase eine große Änderung in seinen APIs. Ich meine: 'com.google.firebase:firebase-messaging:18.0.0'

In 18.0.0 wurden sie entfernt MyFirebaseInstanceIDServiceund Sie müssen ein Token erhalten, MyFirebaseMessagingServicedamit Sie nur schreiben müssen:

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

}

und auch in Ihrer AndroidManifest.xml müssen Sie entfernen:

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

Es wird außerdem empfohlen, Standardwerte festzulegen, um das Erscheinungsbild von Benachrichtigungen anzupassen. Sie können ein benutzerdefiniertes Standardsymbol und eine benutzerdefinierte Standardfarbe angeben, die angewendet werden, wenn in den Benachrichtigungsnutzdaten keine entsprechenden Werte festgelegt sind.

Fügen Sie diese Zeilen in das Anwendungs-Tag ein, um das benutzerdefinierte Standardsymbol und die benutzerdefinierte Farbe festzulegen:

    <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" />

Um Benachrichtigungsnachrichten in einer Hintergrund-App zu verarbeiten, sollten Sie in Ihrer ersten Aktivität eine Absicht definieren, auch wenn es sich um SplashScreen handelt. Wenn sich Ihre App im Hintergrund befindet, leitet Android Benachrichtigungsnachrichten an die Taskleiste weiter. Ein Benutzer, der auf die Benachrichtigung tippt, öffnet standardmäßig den App-Starter.

Zum Beispiel, wenn Ihr Json so ist:

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

Sie müssen nur eine einfache Absicht schreiben, um diese Werte zu erhalten:

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

Zusätzlich zu den obigen Antworten: Wenn Sie Push-Benachrichtigungen mithilfe der FCM-Konsole testen , werden der Schlüssel und das Objekt "Daten" nicht zum Push-Benachrichtigungspaket hinzugefügt. Sie erhalten also keine detaillierte Push-Benachrichtigung, wenn die App im Hintergrund ist oder beendet wurde.

In diesem Fall müssen Sie sich für Ihre Back-End-Administratorkonsole entscheiden, um das App-Hintergrundszenario zu testen.

Hier haben Sie Ihrem Push-Bundle den 'Daten'-Schlüssel hinzugefügt. Daher wird der detaillierte Push wie erwartet angezeigt. Hoffe das hilft wenigen.

Max Droid
quelle
0

Mit diesem Code können Sie die Benachrichtigung im Hintergrund / Vordergrund erhalten und auch folgende Aktionen ausführen:

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

In-App verwenden diesen Code:

  @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
      String key1Data = remoteMessage.getData().get("key1");
      // use key1Data to according to your need
    }
Ashish Kumar
quelle
// Daten sollten in diesem Format von der Benachrichtigung {"bis": "/ xyz / Benachrichtigungen", "Daten": {"Schlüssel1": "Titelbenachrichtigung", "Schlüssel2": "Beschreibungsbenachrichtigung"}} stammen Dieser Code im PHP-Dienst?
Tabish Khan
-3

Es gibt zwei Arten von Benachrichtigungen

  1. Benachrichtigung anzeigen - Nur Benachrichtigungen anzeigen, wird angezeigt. Nur die App ist nicht geöffnet und befindet sich im App-Stapel.
  2. Datenbenachrichtigung - Der Rückruf wird in die onMessageReceived-Methode von firebasemessagingservice verschoben und funktioniert, wenn sich die App im Hintergrund, im Vordergrund oder im Status "Abgebrochen" befindet.

Sie müssen Datenbenachrichtigungen verwenden, um die Benachrichtigung zu verarbeiten, wenn sich die App im Hintergrund befindet.

abhi.nalavade
quelle
-5

Ich habe das gleiche Problem festgestellt und die Firebase-Bibliothek neu kompiliert und verhindert, dass Benachrichtigungen gesendet werden, wenn sich die Anwendung im Hintergrund befindet

* Bibliothek https://github.com/erdalceylan/com-google-firebase-messaging

 dependencies {
        compile 'com.google.firebase:firebase-core:11.2.0'
        compile 'com.github.erdalceylan:com-google-firebase-messaging:v1-11.2.0'
    }

* *

@WorkerThread
public void onMessageReceived(RemoteMessage var1) {
  //your app is in background or foreground all time calling
}

Hoffnung hilft. Viel Glück

Erdal CEYLAN
quelle
2
Keine nützliche Antwort
Ankit Patidar
2
Dies ist ein schrecklicher Vorschlag.
vsecades