Как структурировать систему уведомлений для приложения чата с помощью базы данных Firebase и уведомлений Firebase

Я разрабатываю приложение чата с использованием базы данных Firebase в Android.

Я уже выполнил основное (чат и действия со списком пользователей), но еще не создал систему уведомлений.

Я хочу, чтобы когда пользователь добавлялся к беседе (одиночной или групповой), а другой пользователь записывает новое сообщение в беседу, первый пользователь должен получать уведомление, которое при нажатии открывает активность беседы.

Моя большая дилемма заключается в том, как структурировать службу, которая работает в фоновом режиме, для получения push-уведомления или для прослушивания узла базы данных firebase, на который мне нужно посмотреть, чтобы узнать, есть ли какие-либо сообщения.

Я придумал два разных подхода:

Подход 1. Используйте уведомление firebase

При таком подходе я просто отправляю уведомление о данных от клиента-отправителя всем другим клиентам в разговоре, когда отправитель отправляет сообщение, и поэтому получатель решает показать уведомление (если активность в чате он не открыт) и обработать действие щелчка.

Думаю, с таким подходом я сэкономлю потребление ЦП, а затем и батарею.

Я не понимаю, как зарегистрировать пользователя для получения группового уведомления (уведомления темы), потому что, как я понял, я должен подписать этого клиента на тему, но если приложение работает в фоновом режиме или закрыть, откуда ему известно, что новая группа с пользователем внутри создана и поэтому она должна подписаться на эту тему? Для сценария разговора с двумя пользователями это не проблема, поскольку я могу отправить уведомление непосредственно целевому пользователю без подписки на какую-либо тему.

Подход 2) Прослушивание узла данных базы данных firebase в фоновой службе

При таком подходе мне просто нужно создать загрузочную службу, которая прослушивает определенный узел базы данных (с помощью ValueEventListener) и показывает уведомление, когда данные показывают, что приходит новое сообщение / диалог. Примером узла для прослушивания могут быть следующие данные о невидимых сообщениях:

conversation_user_unseen_messages
    $conversationId1
        $user1: 3
    $conversationId2
        $user2: 1

Затем, если данные показывают новые сообщения / разговоры, клиент приложения Android решит показать системное уведомление.

Я думаю, что при таком подходе будет больше потребление энергии, так как он должен постоянно проверять, есть ли какие-либо новые сообщения в базе данных.

Окончательное рассмотрение

Я нашел очень полезное руководство, написанное мифическим Франк ван Пуффелен, который объясняет, как настроить нужную мне систему с использованием дополнительного серверного компонента (сервер node.js). Мой последний вопрос: нужно ли мне настраивать сервер? Что может быть лучше, чем обработка всего, выполняемая клиентами (например, с использованием HTTP-запросов)?

Какое решение вы считаете лучшим? Большое спасибо.

ИЗМЕНИТЬ

Я все еще разбираюсь в этом, но вот некоторые соображения.

Мне нужно запросить и использовать InstanceID

Идентификатор экземпляра предоставляет уникальный идентификатор для каждого экземпляра ваших приложений.

Поэтому я должен запросить InstanceID, когда пользователь подключен, и InstanceId доступен.

И тогда не используйте темы.

Тематические сообщения оптимизированы для пропускной способности, а не для задержки. Для быстрой и безопасной доставки на отдельные устройства или небольшие группы устройств нацеливайте сообщения на токены, а не на темы.

как сказано в руководстве по тематическим сообщениям, которое вместо этого предлагает нацелить сообщение на токены.

Для этого мне нужно собрать токен пользователя в ссылке на мою пользовательскую базу данных:

users: {
    $userId1: {
        name: "John",
        email: "[email protected]",
        token: "Ax8HiP3Edf7....",
    }
}

а затем, когда мой клиент приложения отправляет новое сообщение, он также должен отправить уведомление для всех пользователей, участвующих в чате, что я уже могу сделать с моей текущей структурой базы данных.

Как мне обрабатывать и собирать запросы? Я реализую серверное приложение node.js, которое подключается к базе данных Firebase и прослушивает запросы уведомлений, сделанные приложением, а затем отправляет запрос уведомления с помощью http-вызова каждому приложение назначения.

Когда мне нужно регистрировать токен пользователя? Когда клиент приложения запускается в первый раз или когда истекает срок действия InstanceID (onTokenRefresh).

Это правильный способ сделать это?

ИЗМЕНИТЬ 2

Я обнаружил большую дыру в реализации FCM. Похоже, я не могу обрабатывать все уведомления, доставляемые приложениям iOs, которые не находятся на переднем плане.

Как указано в документации по уведомлению о данных

В iOS FCM сохраняет сообщение и доставляет его только тогда, когда приложение находится на переднем плане и установило соединение FCM. В Android клиентское приложение получает сообщение с данными в onMessageReceived () и может соответствующим образом обрабатывать пары ключ-значение.

И мне нужно поймать уведомление о данных, даже когда приложение находится в фоновом режиме, мне это нужно специально, потому что я хочу обновить счетчик значков на значке приложения, чтобы пользователь знал, сколько у него непрочитанных сообщений.

Теперь я пробую решение OneSignal, которое может получать уведомления даже в фоновом режиме, оно бесплатное и взаимодействует с GCM. Мне грустно, что я не остаюсь с Google, но если я не могу обновить счетчик значков с помощью FCM, мне придется искать другую сторону.

Любое рассмотрение будет оценено.


person Jackie degli Innocenti    schedule 17.10.2016    source источник


Ответы (2)


Подход 1 - это тот, который вам следует использовать. Руководство Фрэнка использует первый подход, поэтому вам нужно настроить сервер.

Это лучшее решение, чем обработка всего клиентами (например, HTTP-запросов)?

да. Если вы отправите уведомление в клиенте (приложении), ваш ключ API будет открыт (через анализ сети или обратный инжиниринг), и вы определенно захотите этого избежать.

как подписать пользователя на новую тему группы, если приложение закрыто или работает в фоновом режиме?

Похоже, вам нужно создать сопоставление отношений на сервере, вызвав https://iid.googleapis.com/iid/v1/IID_TOKEN/rel/topics/TOPIC_NAME с Authorization: key=YOUR_API_KEY в качестве заголовка, полное описание будет здесь. Следуйте этому руководству, чтобы получить токен идентификатора экземпляра.

Надеюсь, мой ответ отвечает на ваши вопросы. Ваше здоровье :)

person Wilik    schedule 17.10.2016
comment
привет @JackD, у меня нет опыта работы с токеном InstanceID, только тема firebase. Я предлагаю вам создать новый вопрос вместо того, чтобы добавлять вопросы, редактируя сообщение. :) - person Wilik; 19.10.2016
comment
Спасибо. Новый вопрос здесь: stackoverflow.com/questions/40138512/ - person Jackie degli Innocenti; 19.10.2016

Теперь вы можете просто добиться этого с помощью функций firebase ...

Вот мой

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.sendFollowerNotification = 
functions.database.ref('/whatever/{groupUID}/{userUID}/{todoUID}')
.onWrite(async (change, context) => {

  const useruuid = context.params.userUID;
  const thisdata = change.after.val();
  console.log('sendto:'+useruuid);

  var ref = admin.database().ref(`userdatas/${useruuid}/phonetkn`);

return ref.once("value", function(snapshot){
     const payload = {
          notification: {

            image: "default",
            sound:"default",
            vibrate:"true" ,

              title: 'New Mission !',
              body: thisdata.titre ,
              color: '#22c064',
              icon: "notification_icon"
          }
     };
     admin.messaging().sendToDevice(snapshot.val(), payload)

}, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
});


});

//

person Denis Hue    schedule 28.06.2019