渐进式网络应用程序 (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.htmlhttps://github.com/ralscha/blog2019/tree/e39cc479044867f40e4c1e2835f7265ee2532760/webpushhttps://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 (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...