Облачные уведомления Firebase в Интернете с помощью React и Rails
Незадолго до этого я начал читать о Firebase. Перед прочтением у меня создалось впечатление, что это только для облачных уведомлений, но теперь я узнал о различных способах использования и преимуществах сервисов Firebase. Я хотел бы поделиться своим опытом со всеми вами, пожалуйста, не стесняйтесь обсуждать об этом больше, потому что я тоже нахожусь на этапе обучения, и это будет полезно для читателей.
Мы широко знаем Firebase для push-уведомлений на iOS, Android и в Интернете. Я уже использовал FCM на android и ios, несколько дней назад я также делал POC в Интернете. В этом блоге я собираюсь объяснить реализацию push-уведомлений в Интернете.
Push-уведомление в Интернете -
Когда я начал работать над отправкой push-уведомлений в Интернете, у меня возникло так много вопросов, как показано ниже -
1] Как настроить firebase с веб-приложением?
2] Кто может видеть уведомления? Авторизованные пользователи или все пользователи.
3] Нужно ли отправлять уведомление конкретным пользователям?
4] Нужна ли нам подписка по теме?
5] Как управлять уведомлениями на сайтах, которые полностью основаны на api и созданы в библиотеке, такой как react.js или angular framework.
Шаг 1 - Получите сообщения
Настроить учетную запись Firebase -
Я проведу вас через несколько основных шагов по настройке, поскольку это хорошо документировано на веб-сайте Firebase.
1] Создайте проект Firebase в консоли Firebase.
2] Если у вас нет существующего проекта Firebase, нажмите Добавить проект и введите либо имя существующего проекта Google Cloud Platform, либо имя нового проекта. Если у вас уже есть приложений в своем проекте, нажмите Добавить другое приложение на странице обзора проекта. На странице обзора проекта в консоли Firebase нажмите Добавить Firebase в свое веб-приложение.
3] Добавьте ниже настраиваемый фрагмент кода в firebase-messaging-sw.js.
В приведенном ниже примере у меня есть файл служебного работника. Нам нужно сохранить файл сервис-воркера в корне проекта.
/* #Filename - firebase-messaging-sw.js * We can only add firebase-messaging serive in the serive worker others * services not allowed here. */ importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js') importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js') /* Now initialize firebase app in the servie worker. * */ firebase.initializeApp({ apiKey: "AOzaSyAc54587dshfiuedP5uZLio", authDomain: "stage-notifications.firebaseapp.com", databaseURL: "https://stage-notications.firebaseio.com", projectId: "stage-notifications", storageBucket: "stage-notications.appspot.com", messagingSenderId: "916580506" }); //These are example configuration value
Существует множество сервисов Firebase, но в этой статье я сосредоточусь только на обмене сообщениями, для этого мы воспользуемся сервисом ниже.
- firebase-messaging - Firebase Cloud Messaging (FCM)
Добавьте ниже фрагмент после инициализации приложения
/* #Filename - firebase-messaging-sw.js * This retrives firebase messageing instance into service worker to handle * background message.*/ const messaging = firebase.messaging();
Есть разное поведение сообщений
- Приложение на переднем плане
- Приложение в фоновом режиме
- Открыта другая вкладка
- Приложение полностью закрыто
Во всех этих сценариях мы должны получить обратный вызов «onMessage», а когда приложение находится в фоновом режиме, нам нужно обработать функцию setBackgroungMessageHandler (), которая будет обрабатывать сообщения, когда наше приложение находится в фоновом режиме. . Мы можем отображать сообщения, когда приложение находится в фоновом режиме, и, щелкнув уведомление, мы можем вернуть приложение на передний план.
Посмотрите на фрагмент ниже, который обрабатывает сообщения, когда приложение находится в фоновом режиме.
// ##Filename - firebase-messaging-sw.js messaging.setBackgroundMessageHandler(function (payload) { const notificationTitle = payload.data.title; const notificationOptions = { body: payload.data.body, icon: payload.data.icon }; return self.registration.showNotification(notificationTitle, notificationOptions); }); /* Here we have provided body, icon to show inside notification.*/
Пожалуйста, проверьте полностью firebase-messaging-sw.js -
#Filename- firebase-messaging-sw.js /*We can only add firebase-messaging serive in the serive worker others * services not allowed here. */ importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js') importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js') /* Now initialize firebase app in the servie worker. * */ firebase.initializeApp({ apiKey: "AOzaSyAc54587dshfiuedP5uZLio", authDomain: "stage-notifications.firebaseapp.com", databaseURL: "https://stage-notifications.firebaseio.com", projectId: "stage-notifications", storageBucket: "stage-notifications.appspot.com", messagingSenderId: "916580506" }); //These are example configuration value const messaging = firebase.messaging(); messaging.setBackgroundMessageHandler(function (payload) { const notificationTitle = payload.data.title; const notificationOptions = { body: payload.data.body, icon: payload.data.icon }; return self.registration.showNotification(notificationTitle, notificationOptions); });
Резюме сервис-воркера Firebase.
- Импортируйте приложение firebase и обмен сообщениями firebase, это позволяет работнику службы доступа к firebase.
- Инициализируйте все конфигурации Firebase.
- Получите экземпляр обмена сообщениями Firebase для обработки фоновых сообщений.
- Добавьте функцию setBackgroundMessageHandler () для обработки фонового сообщения.
Шаг 2 - Настройте облачный обмен сообщениями в веб-приложении.
После настройки нашего сервис-воркера наша основная задача остается, как работает это уведомление Отправка / Получение?
Для лучшего понимания приведу пример собственного приложения.
У меня 2 разных приложения.
- Приложение «А» для отправки уведомлений в Интернет, iOS и Android.
- Приложение «B» будет получать уведомления, отправленные приложением «A».
Для этого я делаю подписку по теме.
Ждать!! , что теперь такое подписка по теме?
Обмен сообщениями по темам основан на модели публикации / подписки. Время от времени несколько устройств могут подписаться на темы и получать сообщения, отправленные по этой теме. FCM обрабатывает сообщения для доставки сообщений на подписанные устройства. На ios и android плагин FCM предоставляет слушателей, которые всегда будут прослушивать сообщения, но в Интернете нам нужно связать тему с токеном регистрации приложения с помощью FCM api, и тогда веб-приложение может получать уведомления об уникальном экземпляре приложения.
Для получения более подробной информации перейдите по ссылке Подписка по темам в Интернете.
Я создал 3 темы для android, ios и web в серверном приложении «A», так как я хочу отправить 3 разных типа уведомлений на мобильных устройствах и в Интернете. В приложениях для iOS и Android я написал такой код, что приложение всегда будет прослушивать определенную тему, чтобы получать уведомления, но в веб-сценарии это немного отличается.
В Интернете нам нужно запросить разрешение пользователя на показ push-уведомлений в приложении с помощью firebase_messaging.requestPermission (). Если пользователь разрешает показывать уведомление, Firebase создает уникальный токен на клиентском компьютере с помощью firebase_messaging. getToken () api. Затем нам нужно отправить этот уникальный токен в Firebase. Не зная токена, Firebase не может отправлять push-уведомления в нашем приложении. Мы можем передать наш регистрационный токен в FCM с помощью batchAdd api, а затем нам нужно связать нашу тему с уникальным регистрационным токеном приложения, поэтому при срабатывании уведомления FCM отправит это сообщение на наше приложение.
Если пользователь вышел из системы, мы также можем удалить связь с темой и нашим экземпляром приложения, то есть уникальным регистрационным идентификатором, используя deleteToken api, чтобы пользователь не получал уведомления.
Есть несколько других API, которые мы можем использовать для проверки наличия регистрационного токена в FCM, а также для проверки экземпляров приложения BatchRemove. Я не буду много писать об этом, вы можете проверить эти API в приведенной ниже ссылке на документацию по firebase, чтобы вы могли улучшить свой код в соответствии с вашими требованиями. Справочник по серверу
Нам также необходимо зарегистрировать нашего сервис-воркера в браузере, чтобы он всегда прослушивал сообщения. пожалуйста, проверьте нижеприведенный фрагмент.
// #Filename - messaging.js (function() { if('serviceWorker' in navigator) { navigator.serviceWorker.register('/firebase-messaging-sw.js'); } })();
В приведенном ниже коде вы можете проверить, как запросить разрешение, создать токен, обновить токен, проверить, присутствует ли токен в FCM, если нет, то отправить токен в FCM с помощью batchAdd, связать тему с уникальным регистрационным токеном, удалить токен и т. Д.
- messaging.js -
import firebase from 'firebase'; import request from 'utility/restUtils'; import API_ENDPOINT from 'utility/api-endpoints'; if (!firebase.apps.length) { firebase.initializeApp({ apiKey: "AOzaSyAc54587dshfiuedP5uZLio", authDomain: "stage-notifications.firebaseapp.com", databaseURL: "https://stage-notifications.firebaseio.com", projectId: "stage-notifications", storageBucket: "stage-nitifications.appspot.com", messagingSenderId: "916580506" }); } const FIREBASE_MESSAGING = firebase.messaging(); /** * Name : subscribeToNotifications() * Description: This method will request permission to user to show notification on browser. * If user allow to show push notifications then it will procide with rest of the steps. **/export function subscribeToNotifications() { FIREBASE_MESSAGING.requestPermission() .then(() => FIREBASE_MESSAGING.getToken()) .then(token => { handleTokenRefresh(token)}) .catch((err) => { console.log("error getting permission :("); }); } /** * Name : handleTokenRefresh() * Description: This method passes token with firebase api to check if this token is already exist. * We also get topic subscription details in this method so we can check if user is already subscribed * with the tpoic or we need to call api to get him subscribe for topic. **/ function handleTokenRefresh(token) { window.firebaseToken = token; return request.doGetFirebase(API_ENDPOINT.formatUrl(API_ENDPOINT.firebaseTokenDetails, window.firebaseToken)) .then((resp) => resp.json()) .then((res) => { checkSubscription(res) }) .catch(e => console.log("handleRefreshToken: "+e.message)) } /** * Name : checkSubscription() * Description: If registration token is not added in FCM then we add it to firebase * so we could send push notification to added tokens. * Here we are sendign topic "firebase-myWebApp" and unique registration token * of app to relate with each other. **/function checkSubscription(resp) { if(resp) { if(resp.status != 200 || !resp.authorizedEntity || !resp.rel) { var reqBody = { "to" : "/topics/firebase-myWebApp", "registration_tokens" : [`${window.firebaseToken}`] } return request.doPostFirebase(API_ENDPOINT.firebaseBatchAddApi, reqBody) .then((re) => relateAppInstanceWithTopic(re)) .catch(e => console.log("checkSubscription: "+e.message)) } } } /** * Name : relateAppInstanceWithTopic() * Description: This method create relationship mapping with registration token and topic. **/function relateAppInstanceWithTopic(res) { if(res.status == 200 && !res.results) { let params = [ window.firebaseToken, 'firebase-myWebApp' ] return request.doPostFirebase(API_ENDPOINT.formatUrl(API_ENDPOINT.mapTopicWithFirebaseInstance, ...params)) .then((response) => { if(response.status == 200) { console.log('User is subscribed for push notification.') } else { console.log('User is not subscribed for push notification.') } }) .catch(e => console.log(e.message)) } } /** * Name : logoutFirebase() * Description: Delete current user token and also remove current token from firebase database (batch). */export function logoutFirebase() { FIREBASE_MESSAGING.getToken().then((token) => { var fbToken = token; FIREBASE_MESSAGING.deleteToken(token) return fbToken; }) .then((fbToken) => { var reqBody = { "to" : "/topics/firebase-firebase-myWebApp", "registration_tokens" : [`${fbToken}`] } return request.doPostFirebase(API_ENDPOINT.firebaseBatchRemove, reqBody) .then((res) => { if(res.status != 200) { console.log(resp.results.error) } }) .catch(e => console.log("checkSubscription: "+e.message)) }) .catch((err) => { console.log("error deleting token :("); }); } /** * Name : onTokenRefresh() * Description: If token is deleted or expired , we need to create new token for current user * and need to add that token in the firebase database to get push notification. **/ FIREBASE_MESSAGING.onTokenRefresh(function() { FIREBASE_MESSAGING.getToken() .then(function(refreshedToken) { handleTokenRefresh(refreshedToken) .then((resp) => { checkSubscription(resp)}) .catch((err) => { console.log("error getting permission :("); }); }) .catch(function(err) { console.log('Unable to retrieve refreshed token ', err); }); }); /** * Name : onMessage() * Description: When firebase receives push notification for current subscribed topic * this listner will get execute. **/ FIREBASE_MESSAGING.onMessage(function (payload) { console.log("Message received. ", payload); }); (function() { if('serviceWorker' in navigator) { navigator.serviceWorker.register('/firebase-messaging-sw.js'); } })();
Другие необходимые файлы -
- api-endpoints.js -
Здесь я добавил все необходимые API.
let firebaseService = 'https://iid.googleapis.com/iid/' var API_ENDPOINT = { firebaseTokenDetails:`${firebaseService}info/{0}?details=true`, firebaseBatchAddApi:`${firebaseService}v1:batchAdd`, mapTopicWithFirebaseInstance:`${firebaseService}v1/{0}/rel/topics/{1}`, firebaseBatchRemove: `${firebaseService}v1:batchRemove`, formatUrl: function (url) { var args = Array.prototype.slice.call(arguments, 1); return url.replace(/{(\d+)}/g, function(match, number) { return args[number] ? args[number] : match; }); } } export default API_ENDPOINT;
- requestUtils.js -
Я использую isomorphic-fetch для вызовов ajax ..
import fetch from 'isomorphic-fetch'; class Request { constructor() { this._doGetParam = this._doGetParam.bind(this); this._doPostParam = this._doPostParam.bind(this); this.firebaseHeaders = { 'Content-Type': 'application/json', 'Authorization': "key=AOzaSyAc54587dshfiuedP5uZLio" } } _doGetParam (headers) { var params = { method: 'GET', dataType: 'JSON', headers: headers }; return params; }; _doDeleteParam (headers, requestBody) { var params = { method: 'DELETE', dataType: 'JSON', headers: headers, body: JSON.stringify(requestBody) }; return params; }; _doPostParam (headers, requestBody) { var params = { method: 'POST', dataType: 'JSON', headers: headers, body: JSON.stringify(requestBody) }; return params; }; doGetFirebase (url) { var param = this._doGetParam(this.firebaseHeaders) return fetch(url, param) } doPostFirebase (url, body) { var params = this._doPostParam(this.firebaseHeaders, body); return fetch(url, params); } } var request = new Request(); export default request;
Теперь все было о настройке на стороне клиента,
Теперь как отправить уведомление приложению «Б»?
Мы отправляем push-уведомления из приложения «А», написанного на рубине. Мы отправим уведомление с помощью запроса curl, пожалуйста, проверьте его ниже.
#Filename - notifications.rb require 'shellwords' module Notificationdef push_notification(alert) firebase_key = ENV['FIREBASE_KEY'] firebaseApi = "curl -X POST --header 'Authorization: key=#{firebase_key}' --Header 'Content-Type: application/json' https://fcm.googleapis.com/fcm/send -d " alert_title, alert_description = [ActionController::Base.helpers.strip_tags(alert.title), ActionController::Base.helpers.strip_tags(alert.description)] #Notification params for Mobile notificationParams = { notification: { body: alert_description, title: alert_title, sound: 'default', click_action: 'FCM_PLUGIN_ACTIVITY', icon: 'fcm_push_icon', content_available: true }, data: { title: alert_title, body: alert_description, click_action: 'FCM_PLUGIN_ACTIVITY', icon: 'fcm_push_icon' }, priority: "high" } #Notification params for web notificationParamsWeb = { notification: { body: alert_description, title: alert_title, icon: '/apple-touch-icon.png' } } notificationTopicAndroid = { to: '/topics/firebase-android' } notificationTopicIos = { to: '/topics/firebase-ios' } notificationTopicWeb = { to: '/topics/firebase-myWebApp' } requestAndroid = notificationParams.merge(notificationTopicAndroid).to_json requestIos = notificationParams.merge(notificationTopicIos).to_json requestWeb = notificationParamsWeb.merge(notificationTopicWeb).to_json system("#{firebaseApi} #{Shellwords.escape(requestAndroid)}") system("#{firebaseApi} #{Shellwords.escape(requestIos)}") system("#{firebaseApi} #{Shellwords.escape(requestWeb)}") end end
Также подтвердите, что сервисный работник зарегистрирован в вашем браузере.
Я надеюсь, что эта статья поможет людям. Не стесняйтесь оставлять свои отзывы, чтобы мы могли сделать это лучше.
Спасибо,
Калашри Аундхкар