it-swarm.com.de

Umgang mit Benachrichtigungen mit FCM, wenn sich die App im Vordergrund oder Hintergrund befindet

Ich habe Firebase benutzt, um Mein Projekt zu bauen.
Es wird auch die FCM (Firebase-Cloud-Nachricht) verwendet.
Aber es gibt ein Problem.
Ich kann den FCM nicht bearbeiten (meine benutzerdefinierte Benachrichtigung erstellen), wenn sich die App im Hintergrund befindet.

Das offizielle Website-Tutorial sagte das 
Fall 1: App-Vordergrund -> überschreiben Sie "onMessageReceived ()", um Ihre benutzerdefinierte Benachrichtigung zu erstellen. 
Fall 2: App-Hintergrund -> System erstellt die Benachrichtigung direkt. Wir müssen und können nichts tun. In diesem Fall löst es nicht "onMessageReceived ()" aus.

Wenn ich jedoch nichts tun kann, wenn die App im Hintergrund ist, kann ich keine benutzerdefinierte Benachrichtigung erstellen. (z. B. Nach Benutzer klicken auf die Benachrichtigung. Ein Fenster wird geöffnet, in dem Detailinformationen angezeigt werden.)

Wie gehe ich mit FCM mit Benachrichtigungen um, wenn sich die App im Hintergrund befindet?

4
Leon Chang

Es gibt eine schlechte Nachricht.
Google ändert den Firebase-Quellcode in der Version "com.google.firebase: firebase-messaging: 11.6.0".
handelIntent ist jetzt "public final void method". was bedeutet, dass wir es nicht überschreiben können.
Wenn Sie die Lösung verwenden möchten, ändern Sie die Version in "com.google.firebase: firebase-messaging: 11.4.2"



Versuche meinen Weg Es kann perfekt an der Projekt-Build-Version arbeiten, ist Android 6.0 oben (API-Ebene 23) und ich habe es bereits ausprobiert.

Es gibt einen besseren Weg als offizielle Site-Anleitung

Die offizielle Website gab an, dass die Benachrichtigung vom System erstellt wird, wenn sich die App im Hintergrund befindet. Sie können es also nicht umgehen, indem Sie "onMessageReceived ()" überschreiben. Weil "onMessageReceived ()" nur ausgelöst wird, wenn sich die App im Vordergrund befindet.

Aber die Wahrheit ist nicht. Tatsächlich werden die Benachrichtigungen (wenn sich die App im Hintergrund befindet) von Firebase Library erstellt.

Nachdem ich den Code der Firebase-Bibliothek nachverfolgt hatte. Ich finde einen besseren Weg.

Schritt 1. Überschreiben Sie "handleIntent ()" anstelle von "onMessageReceived ()" in FirebaseMessagingService
Warum:
Da die Methode ausgelöst wird, befindet sich die App entweder im Vordergrund oder im Hintergrund. So können wir in beiden Fällen FCM-Nachrichten verarbeiten und unsere benutzerdefinierten Benachrichtigungen erstellen.

@Override
public void handleIntent(Intent intent) {
    Log.d( "FCM", "handleIntent ");
}


Schritt 2. Analysieren Sie die Nachricht von FCM
Wie:
Wenn Sie das Format der von Ihnen festgelegten Nachricht nicht kennen. Drucken Sie es aus und versuchen Sie, es zu analysieren.
Hier ist die grundlegende Abbildung

Bundle bundle = intent.getExtras();
if (bundle != null) {
    for (String key : bundle.keySet()) {
        Object value = bundle.get(key);
        Log.d("FCM", "Key: " + key + " Value: " + value);
    }
}


Schritt 2. Entfernen Sie die von der Firebase-Bibliothek erstellten Benachrichtigungen, wenn sich die App im Hintergrund befindet
Warum:
Wir können unsere benutzerdefinierte Benachrichtigung erstellen. Die von der Firebase Library erstellte Benachrichtigung wird jedoch weiterhin vorhanden sein (Tatsächlich wird sie von "" super.handleIntent (intent) "" erstellt. "Unten finden Sie eine ausführliche Erklärung.). Dann haben wir zwei Benachrichtigungen. Das ist ziemlich komisch. Daher müssen wir die von Firebase Library erstellte Benachrichtigung entfernen

wie (Projekterstellungsstufe ist Android 6.0 oben):
Erkennen Sie die Benachrichtigungen, die wir entfernen möchten, und erhalten Sie die Informationen. Und entfernen Sie sie mit "notificationManager.cancel ()".

private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than Android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
    }


    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "StatusBarNotification tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}

Mein ganzer Beispielcode:

public class MyFirebaseMessagingService extends FirebaseMessagingService {

private static int notificationCount=0;

@Override
public void handleIntent(Intent intent) {
    //add a log, and you'll see the method will be triggered all the time (both foreground and background).
    Log.d( "FCM", "handleIntent");

    //if you don't know the format of your FCM message,
    //just print it out, and you'll know how to parse it
    Bundle bundle = intent.getExtras();
    if (bundle != null) {
        for (String key : bundle.keySet()) {
            Object value = bundle.get(key);
            Log.d("FCM", "Key: " + key + " Value: " + value);
        }
    }

    //the background notification is created by super method
    //but you can't remove the super method. 
    //the super method do other things, not just creating the notification
    super.handleIntent(intent);

    //remove the Notificaitons
    removeFirebaseOrigianlNotificaitons();

    if (bundle ==null)
        return;

    //pares the message
    CloudMsg cloudMsg = parseCloudMsg(bundle);

    //if you want take the data to Activity, set it
    Bundle myBundle = new Bundle();
    myBundle.putSerializable(TYPE_FCM_PLATFORM, cloudMsg);
    Intent myIntent = new Intent(this, NotificationActivity.class);
    myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    myIntent.putExtras(myBundle);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationCount, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    //set the Notification
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.mipmap.icon)
            .setContentTitle(cloudMsg.getTitle())
            .setContentText(cloudMsg.getMessage())
            .setAutoCancel(true)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(notificationCount++, notificationBuilder.build());
}



/**
 * parse the message which is from FCM
 * @param bundle
 */
private CloudMsg parseCloudMsg(Bundle bundle) {
    String title = null, msg=null;

    //if the message is sent from Firebase platform, the key will be that
    msg = (String) bundle.get("gcm.notification.body");

    if(bundle.containsKey("gcm.notification.title"))
    title = (String) bundle.get("gcm.notification.title");

    //parse your custom message
    String testValue=null;
    testValue =  (String) bundle.get("testKey");

    //package them into a object(CloudMsg is your own structure), it is easy to send to Activity.
    CloudMsg cloudMsg = new CloudMsg(title, msg, testValue);
    return cloudMsg;
}


/**
 * remove the notification created by "super.handleIntent(intent)"
 */
    private void removeFirebaseOrigianlNotificaitons() {

    //check notificationManager is available
    NotificationManager notificationManager = 
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    if (notificationManager == null )
        return;

    //check api level for getActiveNotifications()
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        //if your Build version is less than Android 6.0
        //we can remove all notifications instead. 
        //notificationManager.cancelAll();
        return;
     }

    //check there are notifications
    StatusBarNotification[] activeNotifications = 
        notificationManager.getActiveNotifications();
    if (activeNotifications == null)
        return;

    //remove all notification created by library(super.handleIntent(intent))
    for (StatusBarNotification tmp : activeNotifications) {
        Log.d("FCM StatusBarNotification", 
            "tag/id: " + tmp.getTag() + " / " + tmp.getId());
        String tag = tmp.getTag();
        int id = tmp.getId();

        //trace the library source code, follow the rule to remove it.
        if (tag != null && tag.contains("FCM-Notification"))
            notificationManager.cancel(tag, id);
    }
}
}
7
Leon Chang

Wenn ich jedoch nichts tun kann, wenn die App im Hintergrund ist, kann ich keine benutzerdefinierte Benachrichtigung erstellen. (z. B. Nach Benutzer klicken auf die Benachrichtigung. Ein Fenster wird geöffnet, in dem Detailinformationen angezeigt werden.)

Wie gehe ich mit FCM mit Benachrichtigungen um, wenn sich die App im Hintergrund befindet?

Zunächst müssen Sie die richtige Nachrichtennachricht erstellen, die Sie an den fcm-Server senden. Beispiel:

{
  "to": "topic_name",
  "priority": "high",
  "data": {
    "field1": "field1 value" 
    "field2": "field2 value" 
  }

  "notification" : {
      "body" : "Lorem ipsum",
      "title" : "sampke title" 
      "click_action": "SHOW_DETAILS" 
    }
}

data payload sind tatsächliche Daten, die als Nachrichtendetails angezeigt werden sollen, nachdem der Benutzer auf die Benachrichtigung geklickt hat. notification payload gibt an, wie die generierte Benachrichtigung aussehen soll (es können viel mehr Attribute gesetzt werden). Sie müssen keine Benachrichtigung selbst erstellen, sondern nur Sie Hier müssen Eigenschaften festgelegt werden.

Um Ihre Aktivität anzuzeigen, nachdem der Benutzer auf die Benachrichtigung geklickt hat, müssen Sie den Intent-Filter entsprechend click_action einstellen:

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

aktivitäten mit dem oben genannten Absichtsfilter werden automatisch gestartet, wenn der Benutzer auf die Benachrichtigung tippt. Der letzte Schritt besteht im Abrufen von Daten, wenn die Aktivität nach dem Tippen auf die Benachrichtigung gestartet wird. Es ist ziemlich einfach. Benutzerdefinierte Daten werden über ein Bündel an die Aktivität übergeben. In der onCreate-Methode für Ihre Aktivität tun Sie so etwas:

Bundle bundle = getIntent().getExtras();
if(bundle.getString("action").equals("SHOW_DETAILS")) /*This indicates activity is launched from notification, not directly*/
{
 //Data retrieved from notification payload send 
 String filed1 = bundle.getString("field1");
 String filed2 = bundle.getString("field2");
}

Alle oben genannten Punkte sind gültig, wenn die App nicht ausgeführt wird oder sich im Hintergrund befindet. Wenn sich Ihre App im Vordergrund befindet, wird keine Benachrichtigung erstellt. Stattdessen erhalten Sie das Ereignis onMessageReceived(), damit Sie dort mit den gleichen Daten umgehen können (ich denke, Sie wissen wie). 

Referenz:

https://firebase.google.com/docs/cloud-messaging/http-server-refhttps://github.com/firebase/quickstart-Android/tree/master/messaging

1
user1209216

Sie müssen FCM-Datennachrichten verwenden, um eine benutzerdefinierte Benachrichtigung in einer Android-App zu erstellen. Selbst wenn Ihre App im Hintergrund ist, wird onMessageReceived aufgerufen, damit Sie die Daten verarbeiten und die benutzerdefinierte Benachrichtigung anzeigen können.

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

Datennachrichtenformat, das vom Server gesendet werden muss:

{"message":{
"token":"Your Device Token",
"data":{
  "Nick" : "Mario",
  "body" : "great match!",
  "Room" : "PortugalVSDenmark"
}
}
}
1
Rajesh.k

FCM Es wird keine Hintergrundbenachrichtigung gesendet, wenn Ihre App mehr beendet wird und wie Sie in Ihrer Antwort über die handleIntent()-Lösung beschrieben haben. Sie kann für einige Geräte und für eine alte Version funktionieren der FCM, auch wenn Sie eine @override-Methode haben, die nicht in den offiziellen Dokumenten der Firebase beschrieben ist, können Sie hier einige Probleme haben und sie auf Ihrem eigenes Risiko ! anwenden.

Was ist die Lösung?

Sie müssen Ihren eigenen Push-Benachrichtigungsdienst neben FCM wie Telegramm verwenden.

ODER verwenden Sie SYNCADAPTER neben GCM wie Gmail.

Wenn Sie also erfolgreich mit diesen Apps arbeiten möchten, müssen Sie Ihren eigenen Hack verwenden.

0
user6490462