当应用程序处于后台 FCM 中时更新 Web 应用程序用户界面
Posted
技术标签:
【中文标题】当应用程序处于后台 FCM 中时更新 Web 应用程序用户界面【英文标题】:Updating Web App User Interface when application is in background FCM 【发布时间】:2017-07-18 11:50:15 【问题描述】:我正在使用 FCM 处理通知,它可以正常工作,直到我需要从 firebase-messaging-sw.js
更新我的 UI,而我的 Web 应用程序在后台。
我的第一个问题是:是否可以通过服务工作者在后台(当用户不专注于 Web 应用时)更新我的 Web 应用 UI
其次,如果是这样,怎么做?因为我尝试了几件事但它不起作用,显然做错了什么,当它起作用时,我的网络应用程序处于前台。我究竟做错了什么?
我的代码如下。
my-firebase-service-sw.js
// [START initialize_firebase_in_sw]
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase
libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/4.1.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.1.1/firebase-messaging.js');
// My Custom Service Worker Codes
var CACHE_NAME = 'assembly-v0.1.3.1';
var urlsToCache = [
'/',
'lib/vendors/bower_components/animate.css/animate.min.css',
'lib/vendors/bower_components/sweetalert/dist/sweetalert.css',
'lib/css/app_1.min.css',
'lib/css/app_2.min.css',
'lib/css/design.css'
];
var myserviceWorker;
var servicePort;
// Install Service Worker
self.addEventListener('install', function (event)
console.log('installing...');
// Perform install steps
event.waitUntil(
caches.open(CACHE_NAME)
.then(function (cache)
console.log('Opened cache');
return cache.addAll(urlsToCache);
)
);
console.log('installed...');
);
// Service Worker Active
self.addEventListener('activate', function (event)
console.log('activated!');
// here you can run cache management
var cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(function (cacheNames)
return Promise.all(
cacheNames.map(function (cacheName)
if (cacheWhitelist.indexOf(cacheName) === -1)
return caches.delete(cacheName);
)
);
)
);
);
self.addEventListener('fetch', function (event)
event.respondWith(
caches.match(event.request)
.then(function (response)
// Cache hit - return response
if (response)
return response;
// IMPORTANT: Clone the request. A request is a stream and
// can only be consumed once. Since we are consuming this
// once by cache and once by the browser for fetch, we need
// to clone the response.
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function (response)
// Check if we received a valid response
if (!response || response.status !== 200 || response.type !== 'basic')
return response;
// IMPORTANT: Clone the response. A response is a stream
// and because we want the browser to consume the response
// as well as the cache consuming the response, we need
// to clone it so we have two streams.
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function (cache)
cache.put(event.request, responseToCache);
);
return response;
);
)
);
);
self.addEventListener('message', function (event)
console.log("SW Received Message: " + event.data);
// servicePort = event;
event.ports[0].postMessage("SW Replying Test Testing 4567!");
);
myserviceWorker = self;
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp(
'messagingSenderId': '393093818386'
);
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
// [END initialize_firebase_in_sw]
// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START background_handler]
messaging.setBackgroundMessageHandler(function (payload)
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
// send to client
console.log('Sending data to notification');
try
myserviceWorker.clients.matchAll().then(function (clients)
clients.forEach(function (client)
console.log('sending to client ' + client);
client.postMessage(
"msg": "401",
"dta": payload.data
);
)
);
catch (e)
console.log(e);
const notificationTitle = payload.data.title;;
const notificationOptions =
body: payload.data.body,
icon: payload.data.icon,
click_action: "value"
;
return self.registration.showNotification(notificationTitle,
notificationOptions);
);
// [END background_handler]
在我的主 javascript 文件中,它接收有效负载。当应用程序在前台时,它会收到它。我主要关心和问题是当应用程序在后台接收有效负载时,前台的所有活动都可以正常工作。
【问题讨论】:
【参考方案1】:即使您的网站正在打开但没有重点,也可以更新 UI。
获取所有客户端列表后,只需添加启用选项includeUncontrolled
。
示例:
messaging.setBackgroundMessageHandler(function (payload)
console.log('[firebase-messaging-sw.js] Received background message ', payload);
self.clients.matchAll(includeUncontrolled: true).then(function (clients)
console.log(clients);
//you can see your main window client in this list.
clients.forEach(function(client)
client.postMessage('YOUR_MESSAGE_HERE');
)
)
);
在您的主页中,只需为来自服务人员的消息添加侦听器即可。 例如:
navigator.serviceWorker.addEventListener('message', function (event)
console.log('event listener', event);
);
更多详情请见Clients.matchAll()。
【讨论】:
以上是关于当应用程序处于后台 FCM 中时更新 Web 应用程序用户界面的主要内容,如果未能解决你的问题,请参考以下文章
当应用程序处于后台状态时,Google FCM getIntent 未返回预期数据
当应用程序处于后台状态时,Google FCM getIntent 未返回预期数据