有效负载和通知如何在firestore消息传递中工作

时间:2018-05-31 12:35:35

标签: android firebase push-notification firebase-cloud-messaging

我正在使用Firestore创建一个消息传递应用,我希望在发送新消息时发送通知。为此,我使用FCM。

现在我宣布2个有效载荷:通知有效载荷和数据有效载荷。当用户发送消息时,如果应用程序在后台,则收件人会收到2个通知,如果应用程序位于前台,则会收到一个通知。如果我删除通知有效负载,则收件人会收到一个通知,无论该应用是在前台还是后台。

我想要发生的是,当应用在后台或前台时,用户只收到一个通知,如果应用与发件人进行聊天活动,则只收到一个通知。我的理解是,当我声明通知和数据有效负载时,这应该是默认行为。

  

处理后台应用程序中的通知消息

     

当您的应用在后台时,Android会将通知消息定向到系统托盘。用户点按通知会默认打开应用启动器。

     

这包括包含通知和数据有效负载的消息(以及从Notifications控制台发送的所有消息)。在这些情况下,通知会传递到设备的系统托盘,并且数据有效负载将在启动器活动的附加内容中传送。

有人可以帮忙吗?我已阅读http://localhost:8100/build/vendor.js:15472:42this但它似乎并不适合我,所以也许还有其他我不知道的是我的清单条目

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

这是我的消息服务,我现在发送非常基本的通知

{{1}}

2 个答案:

答案 0 :(得分:2)

如果您想避免显示通知,则应在FirebaseMessagingService上对其进行控制。您的条件似乎是您的应用程序在特定活动中处于打开状态。

如果您想在应用程序不在Foreground中时避免通知,那么您应该从服务中检查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" />添加到您的清单。

如果您想在特定活动中避免它。然后,您需要找出一种方法来跟踪该活动的生命周期。使用SharedPreferencesstatic变量...您可以在此post

中看到多个示例

希望它能帮到你!

答案 1 :(得分:1)

根据您的用例,我认为您需要与您的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);
}