J'ai utilisé firebase pour construire mon projet.
Il utilisera également le message FCM (Firebase Cloud Message).
Mais il y a un problème.
Je ne peux pas gérer le FCM (créer ma notification personnalisée) lorsque l'application est en arrière-plan.
Le tutoriel du site officiel dit que
cas 1: Avant-plan de l'application -> remplacer le "onMessageReceived ()" pour créer votre notification personnalisée.
cas 2: Fond de l'application -> Le système créera la notification directement. Nous n'avons pas besoin et ne pouvons rien faire. Parce que cela ne déclenche pas le "onMessageReceived ()" dans ce cas.
Toutefois, si je ne peux rien faire lorsque l'application est en arrière-plan, je ne peux pas créer ma notification personnalisée. (Par exemple, après que les utilisateurs cliquent sur la notification, une fenêtre apparaîtra pour afficher des informations détaillées.)
Alors, comment gérer les notifications avec FCM lorsque l'application est en arrière-plan?
Il y a une mauvaise nouvelle.
Google modifie le code source de Firebase dans la version "com.google.firebase: firebase-messaging: 11.6.0".
handelIntent est maintenant une "méthode de suppression finale publique". ce qui signifie que nous ne pouvons pas le remplacer.
Si vous souhaitez utiliser la solution, remplacez la version par "com.google.firebase: firebase-messaging: 11.4.2"
Essaie ma voie. Il peut parfaitement fonctionner sur la version de construction du projet est Android 6.0 ci-dessus (api niveau 23) et je l’ai déjà essayé.
Il existe un meilleur moyen que tutoriel du site officiel
Le site officiel a déclaré que la notification sera créée par le système lorsque l'application est en arrière-plan. Donc, vous ne pouvez pas le gérer en remplaçant "onMessageReceived ()". Parce que "onMessageReceived ()" n'est déclenché que lorsque l'application est au premier plan .
Mais la vérité n'est pas. En fait, les notifications (lorsque l'application est en arrière-plan) sont créées par Firebase Library.
Après avoir tracé le code de la bibliothèque de base de feu. Je trouve un meilleur moyen.
Étape 1. Remplacez le "handleIntent ()" au lieu de "onMessageReceived ()" dans FirebaseMessagingService.
Pourquoi:
Parce que la méthode sera déclenchée, l'application est au premier plan ou à l'arrière-plan. Nous pouvons donc gérer le message FCM et créer nos notifications personnalisées dans les deux cas.
@Override
public void handleIntent(Intent intent) {
Log.d( "FCM", "handleIntent ");
}
Étape 2. Analyser le message du FCM
Comment:
Si vous ne connaissez pas le format du message que vous avez défini. Imprimez-le et essayez de l'analyser.
Voici l'illustration de base
Bundle bundle = intent.getExtras();
if (bundle != null) {
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
Log.d("FCM", "Key: " + key + " Value: " + value);
}
}
Étape 2. Supprimez les notifications créées par la bibliothèque Firebase lorsque l'application est en arrière-plan.
Pourquoi:
Nous pouvons créer notre notification personnalisée. Mais la notification créée par Firebase Library sera toujours là (en réalité, elle a été créée par "" super.handleIntent (intent) "". Vous trouverez une explication détaillée ci-dessous.). Ensuite, nous aurons deux notifcations. C'est plutôt bizarre. Nous devons donc supprimer la notification créée par Firebase Library.
comment (le niveau de construction du projet est Android 6.0 ci-dessus):
Reconnaître les notifications que nous voulons supprimer et obtenir les informaions. Et utilisez le "notificationManager.cancel ()" pour les supprimer.
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);
}
}
Le tout mon exemple de code:
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);
}
}
}
Toutefois, si je ne peux rien faire lorsque l'application est en arrière-plan, je ne peux pas créer ma notification personnalisée. (Par exemple, après que les utilisateurs cliquent sur la notification, une fenêtre apparaîtra pour afficher des informations détaillées.)
Alors, comment gérer les notifications avec FCM lorsque l'application est en arrière-plan?
Tout d’abord, vous devez créer la charge utile de messages correcte que vous envoyez au serveur fcm. Exemple:
{
"to": "topic_name",
"priority": "high",
"data": {
"field1": "field1 value"
"field2": "field2 value"
}
"notification" : {
"body" : "Lorem ipsum",
"title" : "sampke title"
"click_action": "SHOW_DETAILS"
}
}
La charge data
correspond aux données réelles que vous souhaitez afficher en tant que détails du message une fois que l'utilisateur a cliqué sur la notification. La charge notification
représente l'apparence que devrait avoir la notification générée (il y a beaucoup plus d'attributs possibles à définir), vous n'avez pas besoin de créer la notification vous-même. besoin de définir les propriétés ici.
Pour afficher votre activité après que l'utilisateur ait appuyé sur la notification, vous devez définir un filtre d'intention correspondant à click_action
:
<intent-filter>
<action Android:name="SHOW_DETAILS"/>
<category Android:name="Android.intent.category.DEFAULT"/>
</intent-filter>
ainsi, les activités dont le filtre d'intention est supérieur seront lancées automatiquement lorsque l'utilisateur appuiera sur notification . La dernière étape consiste à extraire les données lorsque l'activité est lancée après avoir cliqué sur Notification. C'est assez facile. Les données personnalisées sont transmises à l'activité via bundle. Dans la méthode onCreate
de votre activité, procédez comme suit:
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");
}
Tout ce qui précède est valable si l'application n'est pas en cours d'exécution ou si elle est en arrière-plan. Si votre application est au premier plan, aucune notification ne sera créée. Au lieu de cela, vous recevrez un événement onMessageReceived()
afin que vous puissiez gérer les mêmes données ici (je suppose que vous savez comment).
Référence:
https://firebase.google.com/docs/cloud-messaging/http-server-refhttps://github.com/firebase/quickstart-Android/tree/master/messaging
Vous devez utiliser les messages de données FCM afin de créer une notification personnalisée dans une application Android. Même si votre application est en arrière-plan, onMessageReceived
sera appelé afin que vous puissiez traiter les données et afficher la notification personnalisée.
https://firebase.google.com/docs/cloud-messaging/Android/receive
Format du message de données à envoyer du serveur:
{"message":{
"token":"Your Device Token",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}
FCM n'enverra pas de notification d'arrière-plan si votre application est supprimée et, comme vous l'avez décrit dans votre réponse à propos de la solution handleIntent()
, elle peut fonctionner pour certains appareils et pour une ancienne version. de la FCM, également si vous utilisez la méthode @override
qui n’est pas décrite dans la documentation officielle de firebase, vous risquez de rencontrer quelques problèmes ici, et vous l’utilisez sur votre risque propre !.
Quelle est la solution?
Vous devez utiliser votre propre service de notification Push à côté de FCM, comme Telegram.
OU en utilisant SYNCADAPTER à côté de GCM comme Gmail.
Donc, si vous en avez besoin pour fonctionner correctement avec ces applications, vous devez utiliser votre propre piratage.