pwa-builder / PWABuilder

The simplest way to create progressive web apps across platforms and devices. Start here. This repo is home to several projects in the PWABuilder family of tools.
https://docs.pwabuilder.com
Other
2.66k stars 280 forks source link

[iOS] Support Push Notifications via Firebase or other service #2434

Open JudahGabriel opened 2 years ago

JudahGabriel commented 2 years ago

The iOS project we're using supports Push Notifications via Firebase. Currently, the code is commented out, and PWABuilder doesn't give any UI for it.

We could uncomment the push notification code and add UI in PWABuilder to allow you to specify your Firebase push notification details.

If Push Notifications are important to you, please šŸ‘ this issue.

DeadWisdom commented 2 years ago

This is the main feature that is literally holding back PWAs from taking over.

Chaphasilor commented 2 years ago

Would this also be possible with plain WebPush? :D

I'm not a fan of being forced to use Firebase, but if it's too much work, I totally understand :)

mlynch commented 2 years ago

If you want to bring your PWA to iOS and Android with push support, definitely check out Capacitor which has support for this already: https://capacitorjs.com/docs/apis/push-notifications and more elaborate guide here: https://capacitorjs.com/docs/guides/push-notifications-firebase

I really wish the PWA Builder team would have looked at Capacitor! It does all the things that are still on the "coming soon" list for this project and Capacitor is very popular, growing, and powering thousands of app store apps already. We could have worked with Microsoft to prioritize adding the Service Worker and Manifest importing features. We would still love to have that conversation!

JudahGabriel commented 2 years ago

@Chaphasilor Probably not, but we'll look into it.

@mlynch Interesting. I'd be glad to chat at least. juhimang @ you know where

JudahGabriel commented 2 years ago

p.s. folks, I'm on vacation this week, so replies may be delayed until next week. Chat with you then.

iflow commented 2 years ago

One issue we discovered with push notification on iOS PWA is that it is very difficult to send notifications to specific users. Instead "Interest" (similar to broadcast or category based) notifications are no issue.

But for user specific messages (i. e. notify a user about a new personal message, account change, etc.) you need the possibility to map an user id with a token/device/registration (many different approaches and vocabulars) of the corresponding notification service (like firebase, onesignal etc.). So the question is: How to get the mapping (user id) of the PWA into the iOS swift code? I think this would require to manually adapt the pwabuilder's generated swift code.

For firebase I found this:

emindeniz99 commented 2 years ago

One issue we discovered with push notification on iOS PWA is that it is very difficult to send notifications to specific users. Instead "Interest" (similar to broadcast or category based) notifications are no issue.

But for user specific messages (i. e. notify a user about a new personal message, account change, etc.) you need the possibility to map an user id with a token/device/registration (many different approaches and vocabulars) of the corresponding notification service (like firebase, onesignal etc.). So the question is: How to get the mapping (user id) of the PWA into the iOS swift code? I think this would require to manually adapt the pwabuilder's generated swift code.

For firebase I found this:

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map.

I know that every push notification system works like this.

SuperPat45 commented 2 years ago

It will be awesome if notification push implementation can simply require VAPID keys and connect to the mozilla notification server.

emptimd commented 2 years ago

We hope this is will be released soon.

iflow commented 2 years ago

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map.

I know that every push notification system works like this.

@emindeniz99 thanks for your input! I think it would be no issue to get the device token and send it to the server. The issue, or rather my missing link is, that at the end you have got a lot device tokens and user ids on the server side and you can not easily map them. Because you do not know which device token belongs to which user id.

grafik

emindeniz99 commented 2 years ago

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map. I know that every push notification system works like this.

@emindeniz99 thanks for your input! I think it would be no issue to get the device token and send it to the server. The issue, or rather my missing link is, that at the end you have got a lot device tokens and user ids on the server side and you can not easily map them. Because you do not know which device token belongs to which user id.

grafik

If you send device token via pwa, you can add user identifier like username as long as device token.

At the native code you should not send only device token. ( for some purpose, you can do this, for example unregistered devices can be prompted to login via notifications. )

tntjstumadre commented 2 years ago

Are local notifications an alternative for this issue?? Thanks in advance

iflow commented 2 years ago

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map. I know that every push notification system works like this.

@emindeniz99 thanks for your input! I think it would be no issue to get the device token and send it to the server. The issue, or rather my missing link is, that at the end you have got a lot device tokens and user ids on the server side and you can not easily map them. Because you do not know which device token belongs to which user

If you send device token via pwa, you can add user identifier like username as long as device token.

At the native code you should not send only device token. ( for some purpose, you can do this, for example unregistered devices can be prompted to login via notifications. )

Yes, we need to send some user identifier with the device token from the device. But how to achieve that? The device does not know about the user, because only webview inside the PWA has got this Information. How to pass the user id through the PWA (Stift code). Or would it be possible to get the device id via Javascript?

emindeniz99 commented 2 years ago

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map. I know that every push notification system works like this.

@emindeniz99 thanks for your input! I think it would be no issue to get the device token and send it to the server. The issue, or rather my missing link is, that at the end you have got a lot device tokens and user ids on the server side and you can not easily map them. Because you do not know which device token belongs to which user

If you send device token via pwa, you can add user identifier like username as long as device token. At the native code you should not send only device token. ( for some purpose, you can do this, for example unregistered devices can be prompted to login via notifications. )

Yes, we need to send some user identifier with the device token from the device. But how to achieve that? The device does not know about the user, because only webview inside the PWA has got this Information. How to pass the user id through the PWA (Stift code). Or would it be possible to get the device id via Javascript?

Yes you can inject javascript from swift code. ā€˜PWAShell.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('push-permission-state', { detail: '(state)' }))")ā€™

instead of emit event, you can set window.devicetoken=XyzVariable.

At the frontend, you can access it.

khmyznikov commented 2 years ago

@emptimd @iflow You can look at my implementation of Push notifications by topics subscribe https://github.com/khmyznikov/ios-pwa-wrap It has the ability to request push notifications permission, subscribe to topics and receive push events. You can start from this and add missing features.

phoheisel commented 2 years ago

When you get device token on swift code, you should send it to web view. So, pwa knows the token so your pwa can send it to server(backend). You should manage your user and token map.

I know that every push notification system works like this.

I'd love to see a Firebase push notification based solution like this.

renegademarketer commented 2 years ago

This is THE main feature stopping us and others from going all-in with PWAs. Please add this functionality soon.

khmyznikov commented 2 years ago

This is THE main feature stopping us and others from going all-in with PWAs. Please add this functionality soon.

Please try this implementation. It's basically the same template but with firebase push enabled.

Wotan6891 commented 2 years ago

Hello,

Yes, please. Thank you.

tntjstumadre commented 2 years ago

I could enable push notification using firebase, apn and the commented code provided. I followed rigorously this tutorial https://www.raywenderlich.com/20201639-firebase-cloud-messaging-for-ios-push-notifications that it is basically an understanding of the commented code provided by PWABuilder, as well as APN and firebase set up (backend part is not covered here). So once I got everything set I managed to set my fcm token as an item in my localstorage using evaluateJS and then get that item with JS and send it to the backend where you connect to firebase (I am using Django). If you are using firebase as well for storage, the tutorial covers that too, all in all there is plenty of info out there to consult.

In WebView.swift in line 144 changed '!=' for '==' to bypass the allowedorigin that makes your app open as Safari View Controller and not in Webview itself. The result if (requestHost.range(of: allowedOrigin) == nil). This is a keypoint in order to set your fcm token to LocalStorage.

For a better UX I also disabled WKAppBoundDomains (line 20 in webview.swift config.limitsNavigationsToAppBoundDomains = false;) to open external webs without seeing the address bar. If you are going to do this, please enable back and forward swipe gestures for a better navigation exp (line 37 in webview.swift webView.allowsBackForwardNavigationGestures = true;)

I tried to sum up the whole process in just a few lines. If you are willing to give it a try, answer this comment. It worked perfectly for me.

emindeniz99 commented 2 years ago

I could enable push notification using firebase, apn and the commented code provided. I followed rigorously this tutorial https://www.raywenderlich.com/20201639-firebase-cloud-messaging-for-ios-push-notifications that it is basically an understanding of the commented code provided by PWABuilder, as well as APN and firebase set up (backend part is not covered here). So once I got everything set I managed to set my fcm token as an item in my localstorage using evaluateJS and then get that item with JS and send it to the backend where you connect to firebase (I am using Django). If you are using firebase as well for storage, the tutorial covers that too, all in all there is plenty of info out there to consult.

In WebView.swift in line 144 changed '!=' for '==' to bypass the allowedorigin that makes your app open as Safari View Controller and not in Webview itself. The result if (requestHost.range(of: allowedOrigin) == nil). This is a keypoint in order to set your fcm token to LocalStorage.

For a better UX I also disabled WKAppBoundDomains (line 20 in webview.swift config.limitsNavigationsToAppBoundDomains = false;) to open external webs without seeing the address bar. If you are going to do this, please enable back and forward swipe gestures for a better navigation exp (line 37 in webview.swift webView.allowsBackForwardNavigationGestures = true;)

I tried to sum up the whole process in just a few lines. If you are willing to give it a try, answer this comment. It worked perfectly for me.

I have not tried yet. But I wanted to add a point. If you want to benefit fromt service workers like cache the website for offline access, you should enable wkappdomainbounds.

khmyznikov commented 2 years ago

@tntjstumadre please share your fcm token passthrough implementation. Things like WKAppBoundDomains and allowedOrigin I'm not recommended to change, because it ruins the whole PWA idea. Just use the Capacitor if you don't care about PWA.

tntjstumadre commented 2 years ago

I do care for PWA dont misunderstand me. I didnt know about SW and WKAppBoundDomains, there is another solution other than turn off, you can add up to 10 items to the WKAppBoundDomains array in info.plist, this will let you navigate to external websites.

What i did is, you recieve your fcm token once the app is initialized, then with evaluateJS add it to your localstorage, here it is very well explained https://stackoverflow.com/questions/44896823/is-there-a-way-to-set-local-storage-in-wkwebview

khmyznikov commented 2 years ago

I do care for PWA dont misunderstand me. I didnt know about SW and WKAppBoundDomains, there is another solution other than turn off, you can add up to 10 items to the WKAppBoundDomains array in info.plist, this will let you navigate to external websites.

It's very simple. For PWA functionality you need a Service Worker to be activated. Without BoundDomains, you can't do it on iOS.

tntjstumadre commented 2 years ago

Thats why I proposed adding up to 10 domains to the WKAppBoundDomians array in your info.plist, without turning it off

khmyznikov commented 2 years ago

Thats why I proposed adding up to 10 domains to the WKAppBoundDomians array in your info.plist, without turning it off

If you need navigation to external websites, just don't include these domains in any domain lists. And than SFSafariViewController should do their job.

WKAppBoundDomians is a list for your PWA domains + domains of login services (like ms authenticate or google). No other external domains should be here.

SivakCR commented 2 years ago

This is the killer feature I'm waiting for.

paolomulas commented 2 years ago

Having this feature would be perfect for every kind of PWA

JudahGabriel commented 2 years ago

Sounds like iOS is getting web push notification support in the near future: https://firt.dev/ios-15.4b

obamando commented 2 years ago

@emindeniz99 thanks for your input! I think it would be no issue to get the device token and send it to the server. The issue, or rather my missing link is, that at the end you have got a lot device tokens and user ids on the server side and you can not easily map them. Because you do not know which device token belongs to which user

If you send device token via pwa, you can add user identifier like username as long as device token. At the native code you should not send only device token. ( for some purpose, you can do this, for example unregistered devices can be prompted to login via notifications. )

Yes, we need to send some user identifier with the device token from the device. But how to achieve that? The device does not know about the user, because only webview inside the PWA has got this Information. How to pass the user id through the PWA (Stift code). Or would it be possible to get the device id via Javascript?

Yes you can inject javascript from swift code. ā€˜PWAShell.webView.evaluateJavaScript("this.dispatchEvent(new CustomEvent('push-permission-state', { detail: '(state)' }))")ā€™

instead of emit event, you can set window.devicetoken=XyzVariable.

At the frontend, you can access it.

I used xxx.webView.evaluateJavaScript("window.devicetoken = xyz") in my project to send my token to my websiteā€™s frontend. It worked perfectly fine. Then I updated my Mac (12.1) and Xcode (13.2.1) to test this on iOS 15. Since then, the variable is nonexistent in my frontend. Sometimes when I build the app the first time on a new device window.devicetoken appears. What could be the problem?

AbidFast commented 1 year ago

Yes we need push notification.....

jaroslawdabrowski commented 1 year ago

Upvote! It would be great to have support for push notifications on iOS

khmyznikov commented 1 year ago

@AbidFast @jaroslawdabrowski Native support of web push should be in 2023. Until then, you can take a look at my repo here. https://github.com/khmyznikov/ios-pwa-wrap it's basically same wrapper but push enabled via bridge.

bettysteger commented 1 year ago

@AbidFast @jaroslawdabrowski I also wrote a PWA wrapper in Flutter => 1 code base for iOS and Android.

The Flutter app embeds a Webview and allows communication between the native iOS/Android app and your JavaScript code (which fixes @iflow's issue): https://github.com/bettysteger/flutter_pwa_wrapper

khmyznikov commented 1 year ago

@bettysteger interesting, but Android already have native support of PWA and web push API.

sumanyu-soniwal commented 1 year ago

@JudahGabriel is this in your roadmap? We are looking forward to this feature. Please help us with a timeline if possible.

marcdp commented 1 year ago

Upvote! It would be great to have support for push notifications on iOS.

SuperPat45 commented 1 year ago

@khmyznikov Native support of web push should be in 2023.

There is a good chance that web notifications will not work in the iOS WebView... So we definitively need this feature in PWA Builder iOS generated app.

khmyznikov commented 1 year ago

@khmyznikov Native support of web push should be in 2023.

There is a good chance that web notifications will not work in the iOS WebView... So we definitively need this feature in PWA Builder iOS generated app.

Need to check this on MacOS first. I will try to do so as soon as I can, but I can't give any ETAs now.

gfsd3v commented 1 year ago

@khmyznikov Safari >= 16.1 now supports web push, anyway this changes this implementation somehow? Or plans to create a separate issue for it? I can help where I can (:

https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers

renegademarketer commented 1 year ago

@khmyznikov Safari >= 16.1 now supports web push, anyway this changes this implementation somehow? Or plans to create a separate issue for it? I can help where I can (:

https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers

Finally, Apple joins the party!!

emindeniz99 commented 1 year ago

@khmyznikov Safari >= 16.1 now supports web push, anyway this changes this implementation somehow? Or plans to create a separate issue for it? I can help where I can (:

https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers

The support is for only mac os safari.

phoheisel commented 1 year ago

Yes important to point out! I think Apple did announce to bring the feature on iOS too tho. But when and how is not yet clear so wouldn't rely on that to much!

@khmyznikov Safari >= 16.1 now supports web push, anyway this changes this implementation somehow? Or plans to create a separate issue for it? I can help where I can (: https://developer.apple.com/documentation/usernotifications/sending_web_push_notifications_in_safari_and_other_browsers

The support is for only mac os safari.

maiconcarraro commented 1 year ago

@tntjstumadre

In WebView.swift in line 144 changed '!=' for '==' to bypass the allowedorigin that makes your app open as Safari View Controller and not in Webview itself. The result if (requestHost.range(of: allowedOrigin) == nil). This is a keypoint in order to set your fcm token to LocalStorage.

For a better UX I also disabled WKAppBoundDomains (line 20 in webview.swift config.limitsNavigationsToAppBoundDomains = false;) to open external webs without seeing the address bar. If you are going to do this, please enable back and forward swipe gestures for a better navigation exp (line 37 in webview.swift webView.allowsBackForwardNavigationGestures = true;)

you're awesome! worked for me

tagmood commented 1 year ago

according https://appleinsider.com/articles/23/02/16/developers-can-send-push-notifications-to-web-apps-in-ios-164

Developers Conference in 2022, a feature for web apps called "Web Push" will arrive in iOS 16.4. It's the same W3C standards-based Web Push that Apple added to Safari 16.1 for macOS Ventura.

waiting for it !!!

SuperPat45 commented 1 year ago

"Web Push" will arrive in iOS 16.4... But only for "Home Screen web apps", not for Browsers themselves or WebWiew.

MatteoGauthier commented 1 year ago

Hey, what's the status of this feature since Webkit / Safari supports WebPush ? https://webkit.org/blog/13878/web-push-for-web-apps-on-ios-and-ipados/

bdhanoa commented 1 year ago

Web Push is already available in iOS 16.4 for PWA's added to the home screen. It doesn't work in WKWebView as pointed out by @SuperPat45.

Is there a solution for PWA builder generated iOS app, or are we still stuck?

khmyznikov commented 1 year ago

@bdhanoa @MatteoGauthier sadly web push works only for PWA installed from Safari, nothing available directly for WKWebView. We still have to use this https://github.com/khmyznikov/ios-pwa-wrap

raghulkrishna commented 1 year ago

is there any update on this with 16.5 push api is enabled by default