Advice, direction on push notifications

Forgive me for: a) the length of this message; b) possibly missing more clear documentation than I’ve found; c) my frustration that will likely be evident at the seeming lack of a cogent direction from Ionic / Capacitor for key mobile app functionality.

Working on an Ionic/React mobile app - 6.1.1; @capacitor/core 4.4. “Alpha” version of the app being distributed through test channels from the stores. Now adding push notifications.

Trying to boil my questions down to their most basic form:

  1. Is there any documentation on integrating push notifications into an Ionic/React app. All of the documentation, official or otherwise, is for Angular. The translation isn’t completely obvious.

  2. Is there either an “official” or a “recommended” position on whether to use the @capacitor/push-notifications plugin or the @capacitor-firebase/messaging plugin? The former seems more official, but it requires changes to AppDelegate.swift - taking us out of the realm of Ionic. The latter seems simpler and more tightly integrated with Firebase, but it’s not from Ionic / Capacitor.

Additional questions based on documentation and guides I’ve come across:

Official Ionic docs

  • This doc doesn’t mention a change to AppDelegate.swift that’s found in another tutorial/guide for using the @capacitor/push-notifications plugin, adding a call to FirebaseApp.configure(), along with “pod” changes - not sure what to make of that

  • The #example code snippet is almost useless. Where and when should those wrapper functions be called?

Full guide to using that plugin with Firebase

  • Unlike in the official doc, the ts import statements are from @capacitor/core (vs. @capacitor/push-notifications). What am I missing there?

  • This is for Angular. Is the translation to React basically a useEffect in a near-the-top component to accomplish this initialization? Any equivalent Ionic/React guides?

Full guide to using the Firebase SDK-based plugin

  • This is for Angular. Any equivalent Ionic/React guides? Same question as above on translating to React?

Thanks for your patience.

I followed this guide for my Vue project with success. Push Notifications - Firebase | Capacitor Documentation The examples are with an Angular app but I didn’t have any issues translating them to work with Vue.

That’s the primary doc I’m using right now. It’s worked for the Android app. Jumping through the iOS hoops now.

If you have any tips or tricks you learned, anything you stumbled over, etc., that you could pass along - I’d appreciate it.

Thanks much.

The only issue I had was not being aware that I needed to use the Firebase token over the Apple APN token when sending a push notification to an iOS device. Updating the AppDelegate.swift file as shown in the docs does the trick to return the Firebase token.

Oh, one other thing is that when the app is in the foreground, the pushNotificationReceived event doesn’t display the notification. You have to create a Local Notification to show it. I do this within the pushNotificationReceived callback. I did this before presentationOptions were supported on Android, so I haven’t testing using that option yet.

I’ve been able to get push notifications delivered to an Android device and to an iOS device. Only moderately painful. :wink:

On iOS, the “received” and “action performed” events were invoked (the second when I tapped the notification). But on Android, I’ve not seen the “action performed” event invoked. So that’s something I’m going to need to figure out, as the app is expected to display a certain screen when certain notifications arrive and are tapped.

In case anyone is lurking, the one thing that almost stumped me was for iOS, in Xcode. All the docs are clear that you have to add the “push notifications” capability to the project. What I didn’t see explicitly stated is that if you’re going to run the app to a physically attached device, Xcode builds and runs it in debug mode. You have to make sure the capability is added to the debug target. It creates a separate .entitlements file. If you don’t, you get an error about “no valid aps-environment entitlement string fond”.

Thanks again for the replies.

Assuming you have something like this to handle the tap?

await PushNotifications.addListener(
    'pushNotificationActionPerformed',
    (notification: ActionPerformed) => {
        if (notification.actionId === 'tap') {
            // Do stuff
        }
    }
)

A couple other notes:

  • Are you creating the channel on Android that your push notification is being sent to via PushNotifications.createChannel?
  • On app initialization, I always clear the listeners and re-register them PushNotifications.removeAllListeners(). Otherwise, I was getting weird results of duplicate listeners.

I have a listener for “pushNotificationActionPerformed.” At present, it doesn’t check the notification or anything like that. It just unconditionally calls “alert()” with a message. The alert displays on iOS but not on Android.

I’m not doing anything with “channels” at this point. Currently, the push notification is being sent from the Firebase dashboard to the whole “app,” i.e. any devices that are currently registered / “listening.” Our app has a use case for something like that (or perhaps “topics”?), but if we do use any of those features, they need to be equally supported for Android and iOS. I just haven’t gotten to that point in my research.

Thanks for the pointer on “removeAllListeners” - I did see some weirdness there.

You need to create a channel and assign the notification to it otherwise Android won’t show it (reference).

Caution: If you target Android 8.0 (API level 26) or higher and post a notification without specifying a notification channel, the notification doesn’t appear and the system logs an error.

Are we talking about the scenario where the Android app raises a notification (vs. the device receiving a notification)?

I ask because I haven’t done anything in the app regarding “channels,” yet the Android device is receiving and displaying notifications that I issue via the Firebase dashboard. Further, none of the tutorials (all of them recent - Dec 2022 or later) mention anything about the need to create a channel to receive notifications. They all expect it to work with just “register” and “addListener”. Also, the Firebase dashboard doesn’t ask for anything related to channel when I create the notification.

So if channels are something that has to happen on Android as part of receiving a notification, I’m probably missing some fundamental concept that none of the tutorials delve into. And if “the system logs an error,” what “system” and where? (Some of these questions are just the stream-of-consciousness ones that come to my mind.)

FYI - the Android device I’m using is SDK 30. So those docs and cautions should apply.

Thanks again.

TBH, I have no idea without testing :grin: All I know is that I am setting a channel via the Firebase SDK that matches what I created in the app.

I did read your last message incorrectly though. I thought you were talking about the notification not showing when you said “alert” but that is your own alert for the pushNotificationActionPerformed event. Have you tested with the app in the background and foreground? Can you do a console.log and look at Dev Tools to see if anything is being outputted?

You can get to Dev Tools for an Android device by going to chrome://inspect/#devices in Chrome.

Yes, by “alert()” I meant the javascript function. So it goes something like this:

  • app calls “register()”
  • javascript alert appears for the “register” listener
  • send notification from the Firebase dashboard
  • normal device push notification appears at top of screen
  • app displays javascript alert for the “pushNotificationReceived” listener
  • tap the alert on the device screen (whether it’s overlaid on this app as it’s active or if I’m on the drag-down notifications screen) => nothing happens

When you say “I am setting a channel via the Firebase SDK that matches what I created in the app” - are you talking about using the Firebase SDK from a back-end app (or at least outside the mobile app) to raise the notification? That’s helpful to know, though it makes me wonder how it’s all managed for both iOS and Android apps - what a mess. I will have to use the Firebase SDK from our back-end app to raise notifications to our mobile app devices.

I can use Chrome’s dev tools - I’ve done that a lot at the “web” level of developing the Ionic app.

A more real-world guide sure would be useful. For someone who hasn’t been steeped in the mobile app dev world for the 15 years that it’s existed, this is essentially boiling the ocean for me.

Thanks again.

Yes, I have a PHP Laravel backend application that sends push notifications to the mobile devices. It is pretty much the same for both iOS and Android. Under the registration listener, I send the FCM token to the backend and save it to the user’s session record for that specific device in our DB. Best practices about FCM tokens can be found here. Then when I need to send a notification to that user’s device, I get their token from the DB and send the message off.

I just started in the native world with Ionic/Capacitor maybe 2 years ago. It’s definitely been a lot of learning and trial and error :upside_down_face:

Maybe share your push notification code. That might help to understand exactly what you are doing and see where a possible issue might lie.

Follow-up…

If the app is in the foreground, I get the “pushNotificationReceived” event. In this case, even if I go to the main screen, then the notifications list and tap the notification, I don’t get the “action performed” event.

If the app is not in the foreground, I get the “pushNotificationActionPerformed” event when I tap the notification. In this case, I do not get the “received” event. Also, I think the app might have crashed. It displayed the alert (plus the console.log) when I activated the app; but when I left and came back, the app did a full restart.

Also… I did notice that in the Firebase dashboard, at the last step before sending the notification, it asks for an optional Android channel. Interesting.

To repeat what I said earlier, I’m doing nothing with channels; but the notifications are coming through. :man_shrugging:

FWIW.

Are you using presentationOptions?

As I mentioned above, I am not using presentationOptions. From my testing, how I got things to work when the app is in the foreground, was to create a local notification within the pushNotificationReceived event. See How to implement Push notifications in Quasar with capacitor 3 - #4 by twestrick.

Then within the LocalNotification listener localNotificationActionPerformed, I run the same logic as pushNotificationActionPerformed.

I am using “presentationOptions.” Sounds like maybe I should see what changes when I remove it.

One thing that I’m pretty sure is different from you experienced is that I am seeing the device notification when the app is in the foreground (i.e. the notification tile dropping down from the top of the screen).

If you recall, why can’t the logic of “action performed” be executed in the “received” event when the app is in the foreground?

Feel like I ought to send you a Chipotle gift card at this point. :wink:

Another question, if you know:

Does the @capacitor/push-notifications plugin support “topics”, as discussed at:

https://firebase.google.com/docs/cloud-messaging/android/topic-messaging

https://firebase.google.com/docs/cloud-messaging/ios/topic-messaging

I don’t see anything in the plugin’s docs or in any of the tutorials I’ve read, but it seems like a fundamental part of what Firebase supports. And topics are the right solution for a certain class of our notifications.

Thanks.

I don’t see why you can’t use the pushNotificationReceived event to do what you need to do. It just depends on your use case.

To handle topics, you would need to use something like capacitor-community/fcm. Or better yet, Capawesome’s plugin which you mentioned in the OP which would replace @capacitor/push-notifications while supporting topics.

Am I reading this right?

They only added the ability to “unregister” the token as of v5.0.0 of the plugin? Which means I’d need to update my entire Capacitor footprint to v5.x?

That looks to be correct. You need to update to Capacitor 5 in the near future anyways (by August 31) to comply with Google’s requirements of supporting API >= 33.

Not sure you’re still monitoring this thread, but on the possibility that you are…

I did get everything updated to Capacitor 5 - thanks for the pointer on that.

I’m now working on the “real” implementation, vs. the POC I was working on earlier. I want to go back to the whole Android “channels” issue. I find it curious that none of the tutorials I came across - all of them recent - said anything about “channels” when it came to Android. And, as was the case for me, push notifications to Android worked for them.

OTOH, if that’s really the “right” way to do it, I want to do it that way. But without any tutorials, examples, etc. which show how it’s supposed to work from the sending side and from the mobile app side, it’s not even clear to me how to do it. So if you know of any tutorials or examples that include the use of “channels” for Android, that would be helpful.

Thanks again for all your responses.