web-dev-qa-db-ja.com

FCM-onMessageReceivedでバッジを設定する

Androidアプリケーションがあります。アプリケーションアイコンに通知番号を表示するために何らかの方法を使用しています。通知を受け取ったときにその番号を設定したいと思います。

通知を受け取ったときに番号を設定する必要があると思ったので、onMessageReceivedメソッド内に設定しました。しかし、私の問題はアプリがバックグラウンドで実行されているときにonMessageReceivedメソッドが呼び出されないため、通知番号が設定されないことです。

以下は私のコードです。 onMessageReceived内に数値を設定します。私はすでにsetBadgeメソッドをテストし、それが機能していることを確認できます。問題は、onMessageReceivedが呼び出されないため、setBadgeも呼び出されず、番号が設定されないことです。

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

これを検索したところ issue で、受信メッセージがdisplay messageの場合、アプリがフォアグラウンドの場合にのみonMessageReceivedが呼び出されることがわかりました。ただし、着信メッセージがdata messageの場合、アプリがバックグラウンドであってもonMessageReceivedが呼び出されます。

しかし、私の友人は通知を送信している人(サーバー側)を教えてくれました、メッセージはすでに表示とデータメッセージの両方として送信されます。彼はデータオブジェクトが満たされていると述べました。

[〜#〜] json [〜#〜]coming messageデータオブジェクトを持っています。

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

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

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

データオブジェクトのみを使用している場合、onMessageReceivedは言われたとおりに呼び出されますが、その時間通知は上部に表示されません。

メッセージがデータメッセージでもある場合にonMessageReceivedが呼び出されないのはなぜですか。データメッセージを処理するために別のことをする必要がありますか?クライアント側のディスプレイメッセージングと同じように機能しますか。

任意の助けいただければ幸いです。前もって感謝します。

9
Hilal

Firebaseサポートから学んだように、今後のjsonにONLY data payloadが含まれていない限り、onMessageReceivedを呼び出す方法はありません。

したがって、データペイロードを使用する必要がありますが、データペイロードを使用する場合は通知を表示しないなので、データペイロード情報を使用してカスタム通知を作成する必要があります。

したがって、私は自分に通知を送信データペイロードを取得したときonMessageReceived内です。また、自分に通知を送信した直後にonMessageReceivedにバッジを設定しました。

次のコードは最終バージョンです。

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

全てに感謝。

5
Hilal

バックグラウンドで通知ペイロードを受信するときに何かを行うには、FirebaseMessagingServiceでzzEをオーバーライドするだけです。メソッド名はバージョン間で変わる可能性があります。@ Overrideをクラスに入力して、それが何を示唆しているかを確認してください。私の場合、私はzzDとzzEを見つけ、それらを試してみると、zzEに必要なデータがあることに気付きました。 zzDのエクストラにはウェイクロックの要素がいくつかありました。 zzEの戻り値は基本的に通知が処理されたかどうかを示すため、trueを返す場合、OSは通知を表示しません。私は、OSが通知を処理できるようにするために、自分の作業が終わった後にsuper.zzE(intent)を返すことを好みます。

バッジの更新は、ShortcutBadgerでサポートされているランチャーでのみ機能します。代わりに、やりたいことはほとんど何でもできます。

これが私のコードです(私の通知にはデータペイロードに「バッジ」が含まれています)。

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では、アプリケーションのアイコンを変更することはできません。これは、プログラムがコンパイルされると、.apkにしっかりと封印されるためです。標準のAPIを使用してプログラムで「描画可能」に変更する方法はありません。そのため、以下のコードはSamsung、Htc、Sonyなどでのみ機能します。

詳細については ここ をクリックしてください

1
Dhina k