aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/org/traccar/notificators/NotificatorFirebase.java52
1 files changed, 46 insertions, 6 deletions
diff --git a/src/main/java/org/traccar/notificators/NotificatorFirebase.java b/src/main/java/org/traccar/notificators/NotificatorFirebase.java
index 9fa2ebaf3..d80354d7d 100644
--- a/src/main/java/org/traccar/notificators/NotificatorFirebase.java
+++ b/src/main/java/org/traccar/notificators/NotificatorFirebase.java
@@ -25,7 +25,10 @@ import com.google.firebase.messaging.ApnsConfig;
import com.google.firebase.messaging.Aps;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingException;
+import com.google.firebase.messaging.MessagingErrorCode;
import com.google.firebase.messaging.MulticastMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.traccar.config.Config;
import org.traccar.config.Keys;
import org.traccar.model.Event;
@@ -34,24 +37,40 @@ import org.traccar.model.Position;
import org.traccar.model.User;
import org.traccar.notification.MessageException;
import org.traccar.notification.NotificationFormatter;
+import org.traccar.session.cache.CacheManager;
+import org.traccar.storage.Storage;
+import org.traccar.storage.StorageException;
+import org.traccar.storage.query.Columns;
+import org.traccar.storage.query.Condition;
+import org.traccar.storage.query.Request;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
@Singleton
public class NotificatorFirebase implements Notificator {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NotificatorFirebase.class);
+
private final NotificationFormatter notificationFormatter;
+ private final Storage storage;
+ private final CacheManager cacheManager;
@Inject
- public NotificatorFirebase(Config config, NotificationFormatter notificationFormatter) throws IOException {
+ public NotificatorFirebase(
+ Config config, NotificationFormatter notificationFormatter,
+ Storage storage, CacheManager cacheManager) throws IOException {
this.notificationFormatter = notificationFormatter;
+ this.storage = storage;
+ this.cacheManager = cacheManager;
InputStream serviceAccount = new ByteArrayInputStream(
config.getString(Keys.NOTIFICATOR_FIREBASE_SERVICE_ACCOUNT).getBytes());
@@ -69,7 +88,8 @@ public class NotificatorFirebase implements Notificator {
var shortMessage = notificationFormatter.formatMessage(user, event, position, "short");
- List<String> registrationTokens = Arrays.asList(user.getString("notificationTokens").split("[, ]"));
+ List<String> registrationTokens = new ArrayList<>(
+ Arrays.asList(user.getString("notificationTokens").split("[, ]")));
MulticastMessage message = MulticastMessage.builder()
.setNotification(com.google.firebase.messaging.Notification.builder()
@@ -92,13 +112,33 @@ public class NotificatorFirebase implements Notificator {
try {
var result = FirebaseMessaging.getInstance().sendMulticast(message);
- for (var response : result.getResponses()) {
+ List<String> failedTokens = new LinkedList<>();
+ var iterator = result.getResponses().listIterator();
+ while (iterator.hasNext()) {
+ int index = iterator.nextIndex();
+ var response = iterator.next();
if (!response.isSuccessful()) {
- throw new MessageException(response.getException());
+ MessagingErrorCode error = response.getException().getMessagingErrorCode();
+ if (error == MessagingErrorCode.INVALID_ARGUMENT || error == MessagingErrorCode.UNREGISTERED) {
+ failedTokens.add(registrationTokens.get(index));
+ }
+ LOGGER.warn("Firebase user {} error", user.getId(), response.getException());
+ }
+ }
+ if (!failedTokens.isEmpty()) {
+ registrationTokens.removeAll(failedTokens);
+ if (registrationTokens.isEmpty()) {
+ user.getAttributes().remove("notificationTokens");
+ } else {
+ user.set("notificationTokens", String.join(",", registrationTokens));
}
+ storage.updateObject(user, new Request(
+ new Columns.Include("attributes"),
+ new Condition.Equals("id", user.getId())));
+ cacheManager.updateOrInvalidate(true, user);
}
- } catch (FirebaseMessagingException e) {
- throw new MessageException(e);
+ } catch (FirebaseMessagingException | StorageException e) {
+ LOGGER.warn("Firebase error", e);
}
}
}