Android 13后台Chrome中Web推送通知点击无法打开URL问题
问题描述
我们的Service Worker监听notificationclick事件,在桌面、旧版Android系统及Android 13的Chrome前台状态下均正常工作,但Android 13系统中Chrome处于后台时,带有URL的推送通知按钮点击后无法打开对应标签页。Service Worker运行状态正常,统计日志可正常上报。
相关代码如下:
self.addEventListener('notificationclick', async function(event) { const log = new Log(TAG); log.setLogLevel(LogLevel.DEBUG); log.d('On notification click: ', event.notification).writeLog(); const data = event.notification.data; event.notification.close(); event.waitUntil(clients.matchAll({ type: 'window', }).then(function(clientList) { for (let i = 0; i < clientList.length; i++) { const client = clientList[i]; if (client.url === '/' && 'focus' in client) { return client.focus(); } } if (clients.openWindow) { if (event.action == 'action-1') { if (data.buttonTopics && data.buttonTopics[0]) topicsSubscribeNotification(data.appKey, data.deviceId, data.buttonTopics[0]); return clients.openWindow(data.actions[0]); } else if (event.action == 'action-2') { if (data.buttonTopics && data.buttonTopics[1]) topicsSubscribeNotification(data.appKey, data.deviceId, data.buttonTopics[1]); return clients.openWindow(data.actions[1]); } else { if (data.topics) topicsSubscribeNotification(data.appKey, data.deviceId, data.topics); return clients.openWindow(data.url); } } })); event.preventDefault(); // send statistics to our api });
我们尝试过简化URL打开逻辑,但问题在Android 13后台Chrome环境下依然存在。
解决方案
针对Android 13 Chrome后台的特殊行为,可从以下几个方向调整代码:
1. 修正客户端匹配逻辑
Android 13后台时,clients.matchAll默认可能无法获取到后台窗口,需添加includeUncontrolled: true参数;同时原代码中用相对路径'/'匹配窗口的逻辑存在误差,建议改用完整URL前缀匹配:
event.waitUntil(clients.matchAll({ type: 'window', includeUncontrolled: true, // 包含未被当前Service Worker控制的后台窗口 }).then(function(clientList) { // 生成完整的根路径URL,避免相对路径匹配误差 const rootUrl = new URL('/', self.location.origin).href; for (let i = 0; i < clientList.length; i++) { const client = clientList[i]; // 匹配根路径及子路径,允许携带查询参数或哈希 if (client.url.startsWith(rootUrl) && 'focus' in client) { return client.focus(); } } // 后续openWindow逻辑 }));
2. 确保clients.openWindow的Promise被正确处理
Android 13后台环境下,需显式等待clients.openWindow的Promise完成,同时添加错误捕获排查问题:
// 重构URL处理逻辑,避免嵌套返回导致流程中断 let targetUrl; if (event.action === 'action-1') { data.buttonTopics?.[0] && topicsSubscribeNotification(data.appKey, data.deviceId, data.buttonTopics[0]); targetUrl = data.actions[0]; } else if (event.action === 'action-2') { data.buttonTopics?.[1] && topicsSubscribeNotification(data.appKey, data.deviceId, data.buttonTopics[1]); targetUrl = data.actions[1]; } else { data.topics && topicsSubscribeNotification(data.appKey, data.deviceId, data.topics); targetUrl = data.url; } if (clients.openWindow && targetUrl) { // 显式等待窗口打开操作,并捕获错误日志 return clients.openWindow(targetUrl).catch(err => { log.e('Failed to open window: ', err).writeLog(); }); }
3. 移除不必要的event.preventDefault()
原代码中event.preventDefault()可能干扰Android 13下的通知点击默认行为,且我们已手动调用event.notification.close(),建议移除该语句。
4. 验证URL合法性
确保data.actions[0]、data.actions[1]、data.url均为完整的HTTPS URL,Android 13对非安全域名的限制更严格,避免使用相对路径。
验证步骤
- 在Android 13设备上将Chrome置于后台,触发推送通知并点击按钮;
- 查看Service Worker日志,确认
targetUrl是否正确、clients.openWindow是否被调用、是否有错误信息; - 测试根路径窗口的聚焦逻辑,避免因匹配失败导致重复打开窗口。
内容的提问来源于stack exchange,提问作者user21720345
相关产品推荐
相关产品推荐

