Как работают полезные нагрузки и уведомления в сообщениях пожарного магазина - PullRequest
0 голосов
/ 31 мая 2018

Я создаю приложение для обмена сообщениями с Firestore и хочу отправлять уведомления при отправке нового сообщения.Для этого я использую FCM.

Сейчас я объявляю 2 полезных нагрузки: полезную нагрузку уведомления и полезную нагрузку данных.Когда пользователь отправляет сообщение, получатель получает 2 уведомления, если приложение находится в фоновом режиме, и одно уведомление, если приложение находится на переднем плане.Если я удалю полезную нагрузку уведомлений, получатель получит одно уведомление, находится ли приложение на переднем плане или в фоновом режиме.

Я хочу, чтобы пользователь получал только одно уведомление, когда приложение находится в фоновом режиме или на переднем плане, и ни одного, если приложение находится в чате с отправителем.Насколько я понимаю, это должно быть поведение по умолчанию, когда я объявляю как уведомления, так и данные.

Обработка уведомлений в фоновом приложении

Когда ваше приложение работает в фоновом режиме, Android перенаправляет уведомления в системный трей.При нажатии пользователем на уведомление по умолчанию открывается панель запуска приложения.

Сюда входят сообщения, содержащие как уведомления, так и полезные данные (и все сообщения, отправленные из консоли уведомлений).В этих случаях уведомление доставляется в системный трей устройства, а полезная нагрузка данных доставляется в дополнениях намерения вашего средства запуска.

Кто-нибудь может помочь?Я прочитал это и это , но, похоже, это не работает для меня, так что, может быть, есть еще кое-что, о чем я не знаю, вот моя декларация

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

Вот моя облачная функция с полезными нагрузками как для уведомлений, так и для данных

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.notifyNewMessage = 
functions.firestore
.document('users/{ID}/contacts/{contactID}/messages/{messageID}')
.onCreate((docSnapshot , context) => {
const message = docSnapshot.data()
const recipientId = message['recipientId']
const senderId = message['sender']
const senderName = message['senderName']

return admin.firestore().doc('users/' + recipientId).get().then(userDoc =>{
    const registrationTokens = userDoc.get('registeredToken')
    const notificationBody = (message['data_type'] === "TEXT") ? 
    message['message'] : "You received a new image message."
    const payload = {
        notification : {
            title : senderName + " sent you a message.",
            body : notificationBody
        },
        data : {
            TITLE : senderName + " sent you a message.",
            BODY : notificationBody,
            USER_NAME : senderName,
            USER_NUMBER : message['sender'],
            CLICK_ACTION : "MessageListActivity",
            MESSAGE : message['message'],
        }
    }

    return 
    admin.messaging().sendToDevice(registrationTokens,payload).then(response 
     => {


    })
  })
})

А вот моя служба обмена сообщениями, куда я сейчас отправляю самое основное уведомление

public class MyFirebaseMessagingService extends FirebaseMessagingService {


private static final int NOTIFICATION_MAX_CHARACTERS = 30;

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    // Check if message contains a data payload.
    if (remoteMessage.getData().size() > 0) {
        Map<String, String> data = remoteMessage.getData();
        if (data.size() > 0) {
            sendNotification(data);
        }
    }
    // Check if message contains a notification payload.
    if (remoteMessage.getNotification() != null) {

    }
}

private void sendNotification(Map<String, String> data) {

    String author = data.get("USER_NAME");
    String title = data.get("TITLE");
    String body = data.get("BODY");
    String id = data.get("USER_NUMBER");
    String message = data.get("MESSAGE");

    Intent intent = new Intent(this, MessageListActivity.class);
    intent.putExtra(Constants.USER_NAME, author);
    intent.putExtra(Constants.USER_NUMBER, id);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    // Create the pending intent to launch the activity
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
            PendingIntent.FLAG_ONE_SHOT);
    if (message.length() > NOTIFICATION_MAX_CHARACTERS) {
        message = message.substring(0, NOTIFICATION_MAX_CHARACTERS) + 
        "\u2026";
    }

    Uri defaultSoundUri = 
    RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new 
    NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_email_black_24dp)

   .setContentTitle(String.format(getString(R.string.notification_message), 
   author))
            .setContentText(message)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

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

    notificationManager.notify(0 /* ID of notification */, 
    notificationBuilder.build());
  }
}

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Учитывая ваш вариант использования, я думаю, вам нужно сообщить службе сообщений FCM о состоянии вашей активности в чате и решить, следует ли представлять уведомление на основе этого.Затем вы можете отправить только часть данных с полезной нагрузкой.

Вы можете попробовать настроить приемник вещания в службе FCM и намерения вещания на основе событий жизненного цикла активности чата, чтобы уведомить службу о необходимости создания уведомления.

В службе сообщений:

private boolean chatActive = false;
private String senderID;

@Override
public void onCreate() {
    super.onCreate();
    LocalBroadcastManager.getInstance(this).registerReceiver(chatReceiver,new IntentFilter("com.mypackage.CHAT_LIFECYCLE_EVENT"));
}

@Override
public void onDestroy() {
    LocalBroadcastManager.getInstance(this).unregisterReceiver(chatReceiver);
    super.onDestroy();
}


private BroadcastReceiver chatReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        chatActive = intent.getBooleanExtra("active",false);
        senderID = intent.getStringExtra("sender");
    }
};

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    //Check for whether chat is active with sender
    if(!(chatActive && remoteMessage.getData().get("USER_NAME").equals(senderID)){
    //sendNotification
    }
}

Затем в чате можно отправлять трансляции во время событий жизненного цикла.

@Override
protected void onPause() {
    super.onPause();
    Intent startNotificationIntent = new Intent();
    startNotificationIntent.setAction("com.mypackage.CHAT_LIFECYCLE_EVENT");
    startNotificationIntent.putExtra("active",false);
    LocalBroadcastManager.getInstance(this).sendBroadcast(startNotificationIntent);
}

@Override
protected void onResume() {
    super.onResume();
    Intent stopNotificationIntent = new Intent();
    stopNotificationIntent.setAction("com.mypackage.CHAT_LIFECYCLE_EVENT");
    stopNotificationIntent.putExtra("active",true);
    stopNotificationIntent.putExtra("sender",someSenderVariable);
    LocalBroadcastManager.getInstance(this).sendBroadcast(stopNotificationIntent);
}
0 голосов
/ 31 мая 2018

Если вы хотите не показывать уведомление, вы должны контролировать его на FirebaseMessagingService.Ваше условие выглядит так, что ваше приложение открыто для определенного вида деятельности.

Если вы хотите избежать уведомлений, когда приложение не на переднем плане, то вам следует проверить ActivityManager из Сервиса.Вы можете использовать этот метод для этого:

public boolean isForeground(String myPackage) {
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> runningTaskInfo = manager.getRunningTasks(1); 
    ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
    return componentInfo.getPackageName().equals(myPackage);
}

Также добавьте <uses-permission android:name="android.permission. REAL_GET_TASKS" /> к вашему манифесту.

На случай, если вы хотите избежать этого только в определенной деятельности.Затем вам нужно найти способ отслеживать время жизни этого действия.Используя SharedPreferences, переменную static ... Вы можете увидеть несколько примеров в этом сообщении

Надеюсь, что это поможет вам!

...