如何解决渐进式网络应用程序 (PWA) 无法在 Android 手机屏幕上弹出推送通知
正在开发需要创建推送通知的 PWA(渐进式网络应用程序),这些通知需要尽可能明显。
与大多数聊天应用程序一样,我希望在移动屏幕上弹出通知。在 Android 9 和 10(未测试其他版本)上,推送通知会发出声音并添加到抽屉中,但不会弹出。 经过一番研究,我发现原生android应用程序需要添加“通知通道”(android oreo添加的功能)才能将应用程序的通知设置设置为“声音和弹出”(弹出也可以称为heads -up) 而不仅仅是“声音”。对于 PWA,我找不到有关此类选项的任何信息。
在我(已安装)PWA 的 android 通知设置中,有一个类别称为“常规”,设置仅是声音,未激活弹出/提示。当我激活它时,通知会按预期弹出。
我的解决方案使用 FCM 和 vapid(因此不需要 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-java
public 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:mhaerdi@gmx.ch");
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,}
)
)
}
});
如您所见,我尝试设置 Urgency 标头并向消息数据(服务器端和客户端)添加优先级,但均无效。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。