Уведомления для андроид, откат data-only
All checks were successful
Build rosetta-wss / build (push) Successful in 1m49s

This commit is contained in:
RoyceDa
2026-03-30 19:12:00 +02:00
parent c1b287986d
commit 855deaa48a
3 changed files with 74 additions and 22 deletions

View File

@@ -10,12 +10,15 @@ import java.util.concurrent.Executors;
import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions; import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.AndroidConfig;
import com.google.firebase.messaging.ApnsConfig; import com.google.firebase.messaging.ApnsConfig;
import com.google.firebase.messaging.Aps; import com.google.firebase.messaging.Aps;
import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;
import im.rosetta.database.repository.UserRepository; import im.rosetta.database.repository.UserRepository;
import im.rosetta.service.dispatch.runtime.PushType;
import im.rosetta.service.services.UserService; import im.rosetta.service.services.UserService;
/** /**
@@ -54,25 +57,50 @@ public class FirebaseDispatcher {
} }
private Message buildMessage(String token, HashMap<String, String> data) { private Message buildMessage(String token, HashMap<String, String> data) {
return Message.builder().putAllData(data) String type = data.get("type");
.setApnsConfig(ApnsConfig.builder() if(type == null){
.setAps(Aps.builder() throw new IllegalArgumentException("Push notification type is required in data");
/** }
* content-available=1 будит приложение на iOS ApnsConfig.Builder apnsConfig = ApnsConfig.builder();
*/ AndroidConfig.Builder androidConfig = AndroidConfig.builder();
.setContentAvailable(true) Message.Builder messageBuilder = Message.builder()
.setSound("default")
.build())
.build())
/**
* Высокий приоритет чтобы разбудить приложение на Android
*/
.setAndroidConfig(
com.google.firebase.messaging.AndroidConfig.builder()
.setPriority(com.google.firebase.messaging.AndroidConfig.Priority.HIGH)
.build())
.setToken(token) .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<String, String> data) { public void sendPushNotification(String publicKey, HashMap<String, String> data) {

View File

@@ -12,6 +12,7 @@ import im.rosetta.database.repository.UserRepository;
import im.rosetta.packet.Packet11Typeing; import im.rosetta.packet.Packet11Typeing;
import im.rosetta.packet.Packet7Read; import im.rosetta.packet.Packet7Read;
import im.rosetta.packet.base.PacketBaseDialog; import im.rosetta.packet.base.PacketBaseDialog;
import im.rosetta.service.dispatch.runtime.PushType;
import im.rosetta.service.services.BufferService; import im.rosetta.service.services.BufferService;
import im.rosetta.service.services.UserService; import im.rosetta.service.services.UserService;
import io.orprotocol.ProtocolException; import io.orprotocol.ProtocolException;
@@ -104,7 +105,7 @@ public class MessageDispatcher {
*/ */
this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){
{ {
put("type", "read"); put("type", PushType.READ);
put("dialog", toPublicKey); put("dialog", toPublicKey);
} }
}); });
@@ -115,7 +116,7 @@ public class MessageDispatcher {
*/ */
this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, new HashMap<>(){ this.firebaseDispatcher.sendPushNotification(groupMembersPublicKeys, new HashMap<>(){
{ {
put("type", "group_message"); put("type", PushType.GROUP_MESSAGE);
put("dialog", toPublicKey.replace("#group:", "")); put("dialog", toPublicKey.replace("#group:", ""));
} }
}); });
@@ -174,7 +175,7 @@ public class MessageDispatcher {
*/ */
this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){ this.firebaseDispatcher.sendPushNotification(fromPublicKey, new HashMap<>(){
{ {
put("type", "read"); put("type", PushType.READ);
put("dialog", toPublicKey); put("dialog", toPublicKey);
} }
}); });
@@ -185,7 +186,7 @@ public class MessageDispatcher {
*/ */
this.firebaseDispatcher.sendPushNotification(toPublicKey, new HashMap<>(){ this.firebaseDispatcher.sendPushNotification(toPublicKey, new HashMap<>(){
{ {
put("type", "personal_message"); put("type", PushType.PERSONAL_MESSAGE);
put("dialog", fromPublicKey); put("dialog", fromPublicKey);
} }
}); });

View File

@@ -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";
}