With Cloud Function I was able to send notifications from one device to the receiving device. However, the notifications after the first message I sent on the chat screen are being sent again with all the notifications before it. One notification in the first message, two notifications in the second message and 3 notifications in the third message continues in this way. Normally it only needs to send one notification for each message. I’ve been trying for hours and I can’t find where the error comes from..
Here, in the event that is triggered every time a new notification file is added under the Notifications/ collection in the firabase database, I set the recipient id as Topic. Since I have subscribed the recipient to this topic, notifications only go to him. I think there is no problem here.
index.js in Cloud functions service
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.androidPushNotification = functions.firestore.document("Notifications/{docId}").onCreate(
(snapshot, context) => {
admin.messaging().sendToTopic(
snapshot.data().userid,
{
notification: {
title: snapshot.data().title,
body: snapshot.data().body
}
}
)
}
);
this is my ChatDetailActivity class. When the message will be sent, I add a file to the Notifications/ directory so that the above notification send event is triggered. I add the title, senirid, name and profilepic information to the title element of this file (I couldn’t find any other way, this came to mind). With the split management, I parse the information while showing the notification and show the notification like that. In the body element, there is the message information that the user sent. I think the problem comes from here because when notification is added here in firestore database, the information of previous messages is added again and the above onCreate event is triggered for old messages. It sounds like there is a simple runtime error. but I couldn’t solve the problem.
private void sendNotification(String recieverid, String body) {
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
firestore.collection("users").document(mUser.getUid()).addSnapshotListener((value, error) -> {
String profilepic;
String name;
if (value != null){
name = value.getString("name");
profilepic = value.getString("profilepic");
Map<String, Object> notification = new HashMap<>();
notification.put("userid", recieverid);
notification.put("title", "Anonim Chat" + "&data" + senderid + "&data" + name + "&data" + profilepic);
notification.put("body", name + ": " + body);
firestore.collection("Notifications").document().set(notification).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Log.w("test-message", "onComplete: bildirim başarıyla eklendi gönderildi");
}
}).addOnFailureListener(e -> Log.e("test-message", "onFailure: " + e.getLocalizedMessage()));
}
});
here is the FirebaseMessagingService class. I am parsing the information in the title object in the notification sent with Cloud Function and showing the notification. I would be very glad if someone could help. I obsessed about this problem.
public class PushNotificationService extends FirebaseMessagingService {
@Override
public void onNewToken(@NonNull String token) {
super.onNewToken(token);
}
@Override
public void onMessageReceived(@NonNull RemoteMessage message) {
super.onMessageReceived(message);
String gelenMesaj = Objects.requireNonNull(message.getNotification()).getTitle();
assert gelenMesaj != null;
String[] dizi = gelenMesaj.split("&data", 100);
Log.w("MESSAGE", "onMessageReceived: SenderID: " + dizi[1]);
String title = dizi[0];
String senderid = dizi[1];
String name = dizi[2];
String profilepic= dizi[3];
if (!ChatDetailActivity.getNotificationSenderId().equals(senderid)){
String body = message.getNotification().getBody();
final String CHANNEL_ID = "HEADS_UP_NOTIFICATIONS";
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"MyNotification",
NotificationManager.IMPORTANCE_HIGH);
channel.enableLights(false);
channel.enableVibration(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
Intent intent = new Intent(getApplicationContext(), ChatDetailActivity.class);
intent.putExtra("userid", senderid);
intent.putExtra("name", name);
intent.putExtra("profilepic", profilepic);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
Notification.Builder notification = new Notification.Builder(this, CHANNEL_ID)
.setContentTitle(title)
.setContentText(body)
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true);
Log.w("BODY", "onMessageReceived: " + body);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
Log.w("NOTIFY", "İzin yok izin istenmeli");
return;
}
NotificationManagerCompat.from(this).notify(1, notification.build());
}
}
}
2
Answers
I changed the method like this and the problem went away. I guess this problem occurred because addSnapShotListener is constantly checking for changes in the database. I got the user information in onCreate() and the problem is fixed.
TL;DR: you’re not telling Cloud Functions that you’re running an asynchronous operation (
sendToTopic
), which causes it to retry.A Cloud Function should always:
Promise
that resolves when it has completed its asynchronous operations.Since you do neither of these, the Cloud Functions runtime assumes something went wrong and retries it.
Since
sendToTopic
returns aPromise
already, we can just return that to Cloud Functions to make things work.Also see the documentation on terminating functions, including the great video series in there.