V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
liuchengfeng1
V2EX  ›  程序员

各位大佬, IOS 应用嵌套网页 H5 项目如何做到推送呢?

  •  
  •   liuchengfeng1 · 212 天前 · 1846 次点击
    这是一个创建于 212 天前的主题,其中的信息可能已经有所发展或是发生改变。

    iOSwzt.png

    目前用的方案是:Service Worker API

    代码是参考这篇文章: https://tahazsh.com/blog/web-push-notifications 在浏览器上可以正常推送,但是在苹果手机 Safari 上没有任何反应 T.T

    下面是代码:

    export default defineNuxtPlugin(async () => {
        let registration
    
        const defaultNotification = {
            title: 'iNotify !',
            body: 'You have a new message.',
            openurl: ''
        }
        function NotifyToServer(config) {
            if (config)
                this.init(config)
        }
        NotifyToServer.prototype = {
            init(config) {
                if (!config)
                    config = {}
                this.key = config.key || 'BDQXntRO2oL7cnk3-CC30T4anHw2D-UGFz8UrzjtuxUKVy9dD3nqxRyxnZSM-ssY1wk976yw945mnmayW1_zyks'
                this.title = config.title || document.title // 标题
                this.notification = config.notification || defaultNotification
                this.onLoadApp()
                return this
            },
            async onLoadApp() {
                // 测试密钥 https://web-push-codelab.glitch.me/
                const YOUR_PUBLIC_KEY = this.key
                console.log('🚀 ~ file: serverNotify.client.js:27 ~ onLoadApp ~ YOUR_PUBLIC_KEY:', YOUR_PUBLIC_KEY)
                // 这里为 false
                if ('serviceWorker' in navigator && 'PushManager' in window) {
                    // 激活 serviceWorker
                    registration = await navigator.serviceWorker.register('./sw.js')
                    console.log('🚀 ~ file: serverNotify.client.js:30 ~ onLoadApp ~ registration:', registration)
                    const permissionResult = await Notification.requestPermission()
                    console.log('🚀 ~ file: serverNotify.client.js:33 ~ onLoadApp ~ permissionResult:', permissionResult)
    
                    if (permissionResult !== 'granted')
                        return
                    try {
                        //  service worker 处于激活状态时,可以使用 PushManager.subscribe() 来订阅推送通知
                        const pushSubscription = await registration.pushManager.subscribe({
                            userVisibleOnly: true,
                            // https://developer.mozilla.org/zh-CN/docs/Web/API/PushManager/subscribe 由服务端生成密钥
                            applicationServerKey: YOUR_PUBLIC_KEY
                        })
                        // 端点及发送数据需要的加密密钥
                        console.log('用户已订阅推送通知 pushSubscription', JSON.stringify(pushSubscription))
                        // 例如显示一条通知
                        // registration.showNotification('订阅成功')
                    }
                    catch (err) {
                        console.log('用户拒绝了推送通知', err)
                    }
                    return this
                }
            },
            send(json) {
                // const title = json.title || this.title
                // // 例如显示一条通知
                // registration.showNotification(title, json)
                navigator.serviceWorker.ready.then(registration => {
                    registration.pushManager.getSubscription().then(subscription => {
                        console.log(`=====>subscription`, subscription)
                        if (subscription) {
                            const title = json.title || this.title
                            // 例如显示一条通知
                            registration.showNotification(title, json)
                            // 使用获取到的订阅信息模拟一个 push 事件
                        }
                        else
                            console.log('无法获取订阅信息')
                    }).catch(error => {
                        console.log('获取订阅信息失败: ', error)
                    })
                })
            }
        }
        const iNotifyToServer = new NotifyToServer({
    
        })
        return {
            provide: { iNotifyToServer }
        }
    })
    
    16 条回复
    sentinelK
        1
    sentinelK  
       212 天前
    没太懂楼主的需求,楼主是想实现截图中的效果,还是简单的 webpush ?
    这是完全两个技术路线和逻辑实现。

    截图中的是 iOS 原生推送。楼主代码实现的是 web 推送。
    okakuyang
        2
    okakuyang  
       212 天前 via iPhone
    苹果的是自己的一套,你要去看苹果关于浏览器推送的文档 ,你网上随便抄一篇大概率是失败,因为苹果不是谷歌 chrome 那套 api 。要看你 h5 是运行在自己的 app 里还是别人的 app 里,自己的 app 就自己加原生的推送,别人的 app 你大概率是做不了任何事情。设想一下打开一个 app ,被这个 app 的三方网页添加了一堆推送,这概率极低。
    kdwnil
        3
    kdwnil  
       212 天前
    要用 safari 的 APNs 需要将网页添加到主屏幕
    liuchengfeng1
        4
    liuchengfeng1  
    OP
       212 天前
    @sentinelK 就是 webpush ,截图意思是想实现这种效果
    liuchengfeng1
        5
    liuchengfeng1  
    OP
       212 天前
    @okakuyang 就是自己的 APP
    0xCyan
        6
    0xCyan  
       212 天前
    我最近做过类似的打包 H5 的 app 实现原生推送功能,用的 expo ,流程比较简单
    参考 https://expo.dev/notifications
    dingdangnao
        7
    dingdangnao  
       212 天前
    用 Bark 凑合凑合得了
    MossFox
        8
    MossFox  
       212 天前
    Safari 的 Web Push 需要作为 PWA 应用添加到主屏幕、并且确保点进去是全屏幕运行的那种才可以使用。
    coolcoffee
        9
    coolcoffee  
       212 天前
    自己的应用难道不应该直接写一个 js bridge ,通过网页调用 iOS native 的能力来获取到设备推送 token 吗?
    liuchengfeng1
        10
    liuchengfeng1  
    OP
       212 天前
    @0xCyan 大佬能细说一下吗,具体怎么操作,感觉接近了
    liuchengfeng1
        11
    liuchengfeng1  
    OP
       212 天前
    用了一个 MagicBell ,看 demo 也能实现在 safari 浏览器中进行推送。地址是: https://webpushtest.com/
    0xCyan
        12
    0xCyan  
       212 天前
    不好意思 链接放错了
    https://docs.expo.dev/versions/latest/sdk/notifications/
    跟着这个流程走就好了,没有难度
    ColdBird
        13
    ColdBird  
       212 天前
    webpush 这套方案本身就是 google 家的,是基于 Web Push Protocol 做的上层实现,在 IOS 不好用很正常。从你的需求来说,应该用 IOS 提供的 H5 方案,如果 IOS 没有提供方案,应该自己在壳(即 IOS app )上通过 bridge 提供推送注册能力给 h5 ,h5 注册之后 IOS 来完成推送
    jiahailiang22
        14
    jiahailiang22  
       212 天前
    挺简单啊 wkwebview 代理方式 调用原生 push 即可 app 壳子里边儿 写推送实现代码,搜索 WKwebview 与 ios 原生交互
    liuchengfeng1
        15
    liuchengfeng1  
    OP
       211 天前
    @0xCyan 大佬有 github demo 吗😂想直接运行看一下效果
    liuchengfeng1
        16
    liuchengfeng1  
    OP
       211 天前
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3388 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:10 · PVG 19:10 · LAX 03:10 · JFK 06:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.