web-dev-qa-db-fra.com

FCM - Création d'un badge dans onMessageReceived

J'ai une application Android, où j'utilise une méthode pour afficher le numéro de notification sur l'icône de l'application. Maintenant, je veux définir ce numéro lorsque la notification est reçue.

Je pensais que je devrais définir le nombre lors de la réception de la notification, je l'ai donc défini dans la méthode onMessageReceived. Mais, mon problème est lorsque mon application est en arrière-plan, la méthode onMessageReceived n'est pas appelée, le numéro de notification n'est donc pas défini.

Voici mon code. J'ai mis le nombre à l'intérieur de onMessageReceived. J'ai déjà testé la méthode setBadge et je peux vérifier qu'il fonctionne. Le problème est que onMessageReceived n'est pas appelé, donc setBadge n'est pas non plus appelé, ce qui ne définit pas le numéro.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {

    // TODO(developer): Handle FCM messages here.
    Log.d(TAG, "From: " + remoteMessage.getFrom());
    Conts.notificationCounter ++;
    //I am setting in here.
    setBadge(getApplicationContext(),Conts.notificationCounter  );
    Log.e("notificationNUmber",":"+ Conts.notificationCounter);

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

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

    // 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.
}
// [END receive_message]



public static void setBadge(Context context, int count) {
    String launcherClassName = getLauncherClassName(context);
    if (launcherClassName == null) {
        Log.e("classname","null");
        return;
    }
    Intent intent = new Intent("Android.intent.action.BADGE_COUNT_UPDATE");
    intent.putExtra("badge_count", count);
    intent.putExtra("badge_count_package_name", context.getPackageName());
    intent.putExtra("badge_count_class_name", launcherClassName);
    context.sendBroadcast(intent);
}

public static String getLauncherClassName(Context context) {

    PackageManager pm = context.getPackageManager();

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);

    List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
    for (ResolveInfo resolveInfo : resolveInfos) {
        String pkgName = resolveInfo.activityInfo.applicationInfo.packageName;
        if (pkgName.equalsIgnoreCase(context.getPackageName())) {
            String className = resolveInfo.activityInfo.name;
            return className;
        }
    }
    return null;
}

Quand j'ai cherché ce issue , j'ai trouvé que si le message à venir est message d'affichage _, onMessageReceived n'est appelé que si app est au premier plan. Mais si le message à venir est message de données} _, onMessageReceived est appelé même si l'application est en arrière-plan.

Mais mon ami m'a dit qui envoie la notification (côté serveur), le message est déjà affiché et un message de données. Il a dit que l'objet de données est rempli.

Voici le JSON pour le message coming, il a data object.

{  
   "to":"my_device_id",
   "priority":"high",

   "notification":{  
      "body":"Notification Body",
      "title":"Notification Title",
      "icon":"myicon",
      "sound":"default"
   },

   "data":{  
      "Nick":"DataNick",
      "Room":"DataRoom"
   }
}

Si je n'utilise que des objets de données, onMessageReceived est appelé comme ils l'ont dit, mais cette notification horaire n'apparaît pas en haut.

Maintenant pourquoi onMessageReceived n’est pas appelé si le message est aussi un message de données. Devrais-je faire quelque chose de différent pour gérer les messages de données? Est-ce que cela fonctionne de la même manière avec la messagerie d'affichage côté client? 

Toute aide serait appréciée. Merci d'avance.

8
Hilal

Pas de possibilité d'appeler onMessageReceived à moins que le JSON à venir ne contienne SEULEMENT les données utiles comme je l'ai appris avec le support de Firebase.

Je dois donc utiliser la charge de données, mais si vous utilisez la charge de données, il ne montre pas de notification en haut, vous devez donc créer votre notification personnalisée à l'aide des informations de charge de données.

Donc, j'ai envoyé une notification à moi-même quand je reçois la charge utile de données dans onMessageReceived . Et j’ai mis le badge sur onMessageReceived juste après l’envoi de la notification à moi-même.

Le code suivant est la version finale.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //for data payload
    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {

        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        title = remoteMessage.getData().get("title");
        sendNotification(remoteMessage.getData().get("body"), title);
        badge = Integer.parseInt(remoteMessage.getData().get("badge"));
        Log.e("notificationNUmber",":"+badge);
        setBadge(getApplicationContext(), badge);

    }
    //for notification payload so I did not use here
    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {

        Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());

    }

    // 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.
}
// [END receive_message]

private void sendNotification(String messageBody, String title) {
    Intent intent = new Intent(this, MainMenuActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, notify_no /* Request code */, intent,
            PendingIntent.FLAG_ONE_SHOT);
    if (notify_no < 9) {
        notify_no = notify_no + 1;
    } else {
        notify_no = 0;
    }
    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_launcher_3_web)
            .setContentTitle(title)
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationManager notificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(notify_no + 2 /* ID of notification */, notificationBuilder.build());
}

Merci pour tout.

5
Hilal

Pour faire des choses lors de la réception de charges de notification en arrière-plan, il suffit de remplacer zzE dans FirebaseMessagingService. Le nom de la méthode peut changer d'une version à l'autre. Tapez simplement @Override dans la classe et voyez ce qu'elle suggère pour vous. Dans mon cas, j'ai trouvé zzD et zzE, et en les essayant, j'ai remarqué que zzE contient les données que je voulais. zzD avait du contenu wakelock dans ses extras. La valeur de retour de zzE indique si la notification a été gérée. Par conséquent, si vous renvoyez true, le système d’exploitation n’affiche pas la notification. Je préfère retourner super.zzE (intention) après avoir terminé mes tâches, pour laisser le système d'exploitation gérer la notification.

La mise à jour du badge ne fonctionnera que sur les lanceurs pris en charge par ShortcutBadger. Vous pouvez faire à peu près tout ce que vous voulez à la place, cependant.

Voici mon code (mes notifications contiennent "badge" dans la charge de données):

public class PushNotificationService extends FirebaseMessagingService
{
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage)
    {
        // This is called when the app is in the foreground
        // Show a custom notification or send a broadcast to update the UI here
    }

    @Override
    public boolean zzE(Intent intent)
    {
        if(intent.hasExtra("badge"))
        {
            try
            {
                ShortcutBadger.applyCount(getApplicationContext(), Integer.parseInt(intent.getStringExtra("badge"));
            }
            catch (Exception e)
            {
                Log.e("failedToParse", "Badge!?");
            }
        }
        // pass the intent through to the non-overriden zzE 
        // to show the default notification. 
        return super.zzE(intent);

        // You could also show a custom notification here
        // and return true instead of this if you 
        // don't want the default notifications.
    }

}
3
Pauli Kettunen

enter image description here

Android sans lanceurs personnalisés ni interfaces tactiles ne permet pas de changer l'icône de l'application, car celle-ci est scellée dans le fichier .apk une fois le programme compilé compilé. Il n’existe aucun moyen de le modifier par programmation en utilisant des API standard. Par conséquent, le code ci-dessous ne fonctionne que pour Samsung, HTC, Sony, etc.

pour plus d'informations, cliquez ici

1
Dhina k