# Firebase Cloud Messaging (FCM) Integration ## Обзор Android приложение использует **Firebase Cloud Messaging (FCM)** для push-уведомлений о новых сообщениях. ## Архитектура ### Клиент (Android) 1. **При старте приложения** (`MainActivity.kt`): - Инициализируется Firebase - Получается FCM токен - Токен отправляется на сервер через протокол 2. **При получении нового токена** (`RosettaFirebaseMessagingService.kt`): - Вызывается `onNewToken()` - Новый токен отправляется на сервер 3. **При получении push-уведомления** (`RosettaFirebaseMessagingService.kt`): - Вызывается `onMessageReceived()` - Показывается системное уведомление - При клике открывается соответствующий чат ### Протокол **Packet ID: 0x0A - PacketPushToken** Формат пакета: ``` [PacketID: 0x0A (2 bytes)] [privateKey: String] [publicKey: String] [pushToken: String] [platform: String] // "android" или "ios" ``` ### Сервер Сервер должен: 1. Получить `PacketPushToken` от клиента 2. Сохранить в БД связку: `publicKey -> fcmToken` 3. При получении нового сообщения для пользователя: - Найти FCM токен по `publicKey` получателя - Отправить push через FCM HTTP API ## Настройка Firebase ### 1. Создать Firebase проект 1. Перейти на [Firebase Console](https://console.firebase.google.com/) 2. Создать новый проект или выбрать существующий 3. Добавить Android приложение ### 2. Настройка Android app **Package name:** `com.rosetta.messenger` 1. В Firebase Console → Project Settings → General 2. Скачать `google-services.json` 3. Поместить файл в `rosetta-android/app/google-services.json` ### 3. Структура google-services.json ```json { "project_info": { "project_number": "YOUR_PROJECT_NUMBER", "project_id": "your-project-id", "storage_bucket": "your-project-id.appspot.com" }, "client": [ { "client_info": { "mobilesdk_app_id": "1:YOUR_PROJECT_NUMBER:android:xxxxx", "android_client_info": { "package_name": "com.rosetta.messenger" } }, "oauth_client": [], "api_key": [ { "current_key": "YOUR_API_KEY" } ], "services": { "appinvite_service": { "other_platform_oauth_client": [] } } } ], "configuration_version": "1" } ``` ### 4. Получить Server Key 1. Firebase Console → Project Settings → Cloud Messaging 2. Скопировать **Server Key** (Legacy) 3. Использовать на сервере для отправки уведомлений ## Отправка Push-уведомлений с сервера ### FCM HTTP v1 API (рекомендуется) ```bash POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json { "message": { "token": "FCM_DEVICE_TOKEN_FROM_CLIENT", "notification": { "title": "Имя отправителя", "body": "Текст сообщения" }, "data": { "type": "new_message", "sender_public_key": "SENDER_PUBLIC_KEY", "sender_name": "Имя отправителя", "message_preview": "Текст сообщения" }, "android": { "priority": "HIGH", "notification": { "channel_id": "messages", "sound": "default", "notification_priority": "PRIORITY_HIGH" } } } } ``` ### Legacy FCM API (проще для начала) ```bash POST https://fcm.googleapis.com/fcm/send Authorization: key=YOUR_SERVER_KEY Content-Type: application/json { "to": "FCM_DEVICE_TOKEN_FROM_CLIENT", "notification": { "title": "Имя отправителя", "body": "Текст сообщения", "sound": "default" }, "data": { "type": "new_message", "sender_public_key": "SENDER_PUBLIC_KEY", "sender_name": "Имя отправителя", "message_preview": "Текст сообщения" }, "priority": "high", "android": { "priority": "HIGH", "notification": { "channel_id": "messages" } } } ``` ## Пример серверной логики (Node.js) ```javascript const admin = require("firebase-admin"); // Инициализация Firebase Admin SDK const serviceAccount = require("./path/to/serviceAccountKey.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), }); // База данных с токенами (пример) const userTokens = new Map(); // publicKey -> fcmToken // Обработка PacketPushToken (0x0A) function handlePushToken(packet) { const { publicKey, pushToken, platform } = packet; console.log(`📱 Saving FCM token for user ${publicKey.slice(0, 10)}...`); userTokens.set(publicKey, pushToken); } // Отправка push-уведомления async function sendPushNotification( recipientPublicKey, senderPublicKey, senderName, messageText ) { const fcmToken = userTokens.get(recipientPublicKey); if (!fcmToken) { console.log("⚠️ No FCM token for user"); return; } const message = { token: fcmToken, notification: { title: senderName, body: messageText, }, data: { type: "new_message", sender_public_key: senderPublicKey, sender_name: senderName, message_preview: messageText, }, android: { priority: "HIGH", notification: { channelId: "messages", sound: "default", priority: "PRIORITY_HIGH", }, }, }; try { const response = await admin.messaging().send(message); console.log("✅ Push notification sent:", response); } catch (error) { console.error("❌ Error sending push:", error); // Если токен невалиден - удаляем из БД if ( error.code === "messaging/invalid-registration-token" || error.code === "messaging/registration-token-not-registered" ) { userTokens.delete(recipientPublicKey); } } } // Когда приходит PacketMessage function handleNewMessage(packet) { const { fromPublicKey, toPublicKey, content } = packet; // Отправляем push получателю (если он не онлайн) sendPushNotification(toPublicKey, fromPublicKey, "User", "New message"); } ``` ## Тестирование ### 1. Проверка токена ```kotlin // В логах Android Studio должно быть: 🔔 FCM token: XXXXXXXXXXXX... ``` ### 2. Тест через Firebase Console 1. Firebase Console → Cloud Messaging 2. Send test message 3. Вставить FCM токен из логов 4. Отправить ### 3. Проверка формата пакета ``` Packet 0x0A должен содержать: - PacketID: 0x0A (10 в decimal) - privateKey: хеш приватного ключа - publicKey: публичный ключ пользователя - pushToken: FCM токен устройства - platform: "android" ``` ## Troubleshooting ### Токен не получается 1. Проверить `google-services.json` в `app/google-services.json` 2. Проверить package name совпадает: `com.rosetta.messenger` 3. Rebuild проект 4. Проверить Google Play Services на устройстве ### Уведомления не приходят 1. Проверить разрешение на уведомления (Android Settings) 2. Проверить Server Key на сервере 3. Проверить FCM токен актуален 4. Проверить формат JSON в FCM API запросе ### Уведомления приходят, но не открывают чат Проверить data payload содержит `sender_public_key` ## Полезные ссылки - [Firebase Console](https://console.firebase.google.com/) - [FCM Documentation](https://firebase.google.com/docs/cloud-messaging) - [Android Setup Guide](https://firebase.google.com/docs/cloud-messaging/android/client) - [FCM HTTP Protocol](https://firebase.google.com/docs/cloud-messaging/http-server-ref)