本文介绍了渐进式网络应用程序(PWA)无法在Android手机屏幕上弹出推送通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
使用需要创建推送通知的PWA(渐进式Web应用),这些推送通知需要尽可能明显。
像大多数聊天应用程序一样,我希望通知弹出在移动屏幕上。在安卓9和10(未测试其他版本)上,推送通知会发出声音,并被添加到抽屉中,但不会弹出。经过一些研究,我发现Android原生应用程序需要添加通知频道&(Android Oreo中添加的功能),才能将应用程序的通知设置设置为声音和弹出窗口(也可以称为Head-up),而不是只设置声音和声音。对于PWA,我找不到有关此类选项的任何信息。
在我的(已安装的)PWA的Android通知设置中,有一个类别称为&General";,设置为Only Sound,未激活弹出/提示窗口。当我激活它时,会按预期弹出通知。
我的代码使用带有VAPID的FCM(因此不需要Firebase帐户),灵感来自https://golb.hplar.ch/2019/08/webpush-java.html、https://github.com/ralscha/blog2019/tree/e39cc479044867f40e4c1e2835f7265ee2532760/webpush和https://github.com/web-push-libs/webpush-javapublic class PushMessage {
private final String title;
private final String body;
private final String priority = "high";
public PushMessage(String title, String body) {
this.title = title;
this.body = body;
}
public String getTitle() {
return this.title;
}
public String getBody() {
return this.body;
}
public String getPriority() {
return this.priority;
}
@Override
public String toString() {
return "PushMessage [title=" + this.title + ", body=" + this.body + "]";
}
}
private boolean sendPushMessage(PushMessage message, Subscription subscription) throws Exception {
boolean sent = false;
// send message to given subscription
byte[] encryptedMessage = new CryptoService().encrypt(
new ObjectMapper().writeValueAsString(message),
subscription.getKeys().getP256dh(), subscription.getKeys().getAuth(), 0);
ECPrivateKey eCprivateKey = (ECPrivateKey) new CryptoService().convertPKCS8ToECPrivateKey(privateBytes);
String origin = null;
try {
URL url = new URL(subscription.getEndpoint());
origin = url.getProtocol() + "://" + url.getHost();
} catch (MalformedURLException e) {
e.printStackTrace();
//Application.logger.error("create origin", e);
return true;
}
long expiry = new Date().getTime() + 12 * 60 * 60 * 1000;
JwtClaimsBuilder claimsBuilder = Jwt.claims().audience(origin).subject("mailto:[email protected]");
JwtSignatureBuilder signBuilder = claimsBuilder.jws();//.algorithm(SignatureAlgorithm.ES256);
String token = signBuilder.sign(eCprivateKey);
URI endpointURI = URI.create(subscription.getEndpoint());
Builder httpRequestBuilder = HttpRequest.newBuilder();
if (encryptedMessage != null) {
httpRequestBuilder.POST(BodyPublishers.ofByteArray(encryptedMessage))
.header("Content-Type", "application/octet-stream")
.header("Content-Encoding", "aes128gcm");
}
else {
httpRequestBuilder.POST(BodyPublishers.ofString(""));
}
HttpRequest request = httpRequestBuilder.uri(endpointURI).header("TTL", "86400")
.header("Urgency", "high")
.header("Authorization","vapid t=" + token + ", k=" + publicBase64)
.build();
try {
HttpResponse<Void> response = HttpClient.newHttpClient().send(request,
BodyHandlers.discarding());
switch (response.statusCode()) {
case 201:
log.info("Push message successfully sent: "+ subscription.getEndpoint());
sent = true;
break;
case 404:
case 410:
log.warn("Subscription not found or gone: "+ subscription.getEndpoint());
removeSubscription(subscription);
sent = false;
break;
case 429:
log.error("Too many requests: "+ request);
sent = false;
break;
case 400:
log.error("Invalid request: "+ request);
sent = false;
break;
case 413:
log.error("Payload size too large: "+ request);
sent = false;
break;
default:
log.error("Unhandled status code: "+ response.statusCode() + " "+ request);
sent = false;
}
}
catch (IOException | InterruptedException e) {
log.error("send push message", e);
}
return sent;
}
client side service worker:
self.addEventListener('push', event => {
console.log('Push Notification received: ', event);
if(event.data) {
let data = JSON.parse(event.data.text())
event.waitUntil(
self.registration.showNotification(
data.title,
{
body: data.body,
icon: 'icons/icon-128x128.png',
badge: 'icons/icon-128x128.png',
//image: data.imageUrl,
image: 'icons/icon-128x128.png',
vibrate: [100, 50, 100],
priority: 'max',
android:{
priority: 'max'
},
data: {
dateOfArrival: Date.now(),
primaryKey: 1,
openUrl: 'https://comunex.ch',//data.openUrl
priority: 'max'
},
actions: [
{action: 'explore', title: 'Nice!',
//icon: 'images/checkmark.png'
},
{action: 'close', title: 'Close notification',
//icon: 'images/xmark.png'
},
],
requireInteraction : true,
}
)
)
}
});
如您所见,我尝试设置了紧急标头并向消息数据(服务器端和客户端)添加了优先级,但都没有效果。
推荐答案
我认为您自己已经回答了您的问题。Android应用程序需要被授予显示弹出窗口的权限,除非你授予该权限,否则你不会看到弹出窗口。这是Android生态系统的限制,而不是Web推送协议或此库的限制。
这篇关于渐进式网络应用程序(PWA)无法在Android手机屏幕上弹出推送通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!