diff --git a/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java b/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java index 9a83348..5367b0a 100644 --- a/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java +++ b/src/main/java/im/rosetta/service/dispatch/FirebaseDispatcher.java @@ -10,12 +10,15 @@ import java.util.concurrent.Executors; import com.google.auth.oauth2.GoogleCredentials; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.AndroidConfig; import com.google.firebase.messaging.ApnsConfig; import com.google.firebase.messaging.Aps; import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; import im.rosetta.database.repository.UserRepository; +import im.rosetta.service.dispatch.runtime.PushType; import im.rosetta.service.services.UserService; /** @@ -54,25 +57,50 @@ public class FirebaseDispatcher { } private Message buildMessage(String token, HashMap data) { - return Message.builder().putAllData(data) - .setApnsConfig(ApnsConfig.builder() - .setAps(Aps.builder() - /** - * content-available=1 будит приложение на iOS - */ - .setContentAvailable(true) - .setSound("default") - .build()) - .build()) - /** - * Высокий приоритет чтобы разбудить приложение на Android - */ - .setAndroidConfig( - com.google.firebase.messaging.AndroidConfig.builder() - .setPriority(com.google.firebase.messaging.AndroidConfig.Priority.HIGH) - .build()) + String type = data.get("type"); + if(type == null){ + throw new IllegalArgumentException("Push notification type is required in data"); + } + ApnsConfig.Builder apnsConfig = ApnsConfig.builder(); + AndroidConfig.Builder androidConfig = AndroidConfig.builder(); + Message.Builder messageBuilder = Message.builder() .setToken(token) - .build(); + .putAllData(data); + switch(type) { + case PushType.READ: + /** + * Тихий тип уведомления для очистки отправленных уведомлений на устройстве, + * не должен отображаться пользователю, поэтому не задаем звук и ставим contentAvailable для iOS и high priority для Android + */ + apnsConfig.setAps(Aps.builder().setContentAvailable(true).setSound("default").build()); + androidConfig.setPriority(AndroidConfig.Priority.HIGH); + messageBuilder.setApnsConfig(apnsConfig.build()); + messageBuilder.setAndroidConfig(androidConfig.build()); + break; + case PushType.PERSONAL_MESSAGE: + case PushType.GROUP_MESSAGE: + /** + * Уведомление о новом сообщении, должно отображаться пользователю, поэтому задаем звук и high priority для Android + */ + String body = type == PushType.PERSONAL_MESSAGE ? "New message" : "New group message"; + apnsConfig.setAps(Aps.builder().setSound("default").setMutableContent(true).build()); + androidConfig.setPriority(AndroidConfig.Priority.HIGH); + messageBuilder.setApnsConfig(apnsConfig.build()); + messageBuilder.setNotification(Notification.builder().setTitle( + data.getOrDefault("title", "Rosetta") + ).setBody(body).build()); + messageBuilder.setAndroidConfig(androidConfig.build()); + break; + case PushType.CALL: + /** + * Звонок для андроид используем high priority, чтобы уведомление доставлялось даже если устройство в режиме Doze, + * для iOS используем VoIP уведомление, которое доставляется даже если приложение убито + */ + androidConfig.setPriority(AndroidConfig.Priority.HIGH); + messageBuilder.setAndroidConfig(androidConfig.build()); + break; + } + return messageBuilder.build(); } public void sendPushNotification(String publicKey, HashMap data) { diff --git a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java index ebda611..089ba6b 100644 --- a/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java +++ b/src/main/java/im/rosetta/service/dispatch/MessageDispatcher.java @@ -12,6 +12,7 @@ import im.rosetta.database.repository.UserRepository; import im.rosetta.packet.Packet11Typeing; import im.rosetta.packet.Packet7Read; import im.rosetta.packet.base.PacketBaseDialog; +import im.rosetta.service.dispatch.runtime.PushType; import im.rosetta.service.services.BufferService; import im.rosetta.service.services.UserService; import io.orprotocol.ProtocolException; @@ -104,7 +105,7 @@ public class MessageDispatcher { */ this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ { - put("type", "read"); + put("type", PushType.READ); put("dialog", toPublicKey); } }); @@ -115,7 +116,7 @@ public class MessageDispatcher { */ this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, new HashMap<>(){ { - put("type", "group_message"); + put("type", PushType.GROUP_MESSAGE); put("dialog", toPublicKey.replace("#group:", "")); } }); @@ -174,7 +175,7 @@ public class MessageDispatcher { */ this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ { - put("type", "read"); + put("type", PushType.READ); put("dialog", toPublicKey); } }); @@ -185,7 +186,7 @@ public class MessageDispatcher { */ this.firebaseDispatcher.sendPushNotification(toPublicKey, new HashMap<>(){ { - put("type", "personal_message"); + put("type", PushType.PERSONAL_MESSAGE); put("dialog", fromPublicKey); } }); diff --git a/src/main/java/im/rosetta/service/dispatch/runtime/PushType.java b/src/main/java/im/rosetta/service/dispatch/runtime/PushType.java new file mode 100644 index 0000000..4b8e771 --- /dev/null +++ b/src/main/java/im/rosetta/service/dispatch/runtime/PushType.java @@ -0,0 +1,23 @@ +package im.rosetta.service.dispatch.runtime; + +/** + * Типы PUSH уведомлений, которые отправляются клиентам при получении новых сообщений, звонков и т.д. + */ +public class PushType { + /** + * Новое личное сообщение + */ + public static final String PERSONAL_MESSAGE = "personal_message"; + /** + * Новое групповое сообщение + */ + public static final String GROUP_MESSAGE = "group_message"; + /** + * Входящий звонок + */ + public static final String CALL = "call"; + /** + * Прочтение сообщения для очистки отправленных уведомлений + */ + public static final String READ = "read"; +}