Push notifications beyond the basics
01 Dec 2021Push notifications are a great way to communicate with your users. They let you inform the user about what’s going on. Another good usecase is to remind potentially lost users about your app (a user who didn’t use the app in a while).
In this article, I’m gonna assume you know the basics of push notifications. If you’ve never implemented them yet, check out for example the Firebase Cloud Messaging getting started guide.
Today I want to talk about improving the user experience of push notifications. Sure, the basics work, but I think we can do better. One way to improve the UX is to think about these two cases:
- The user receives a notification while the app is in the foreground
- The user launches your app and has an active notification
Usually, we attach notification actions only to opening the notification, but that doesn’t have to be that way.
I recently thought about this for EventBattle - a scavenger hunt mobile game. We want to ask our users for feedback once they played for a while and we use push notifications for that. Let’s think about the two cases listed above. If the app is in the foreground, we can show the feedback dialog right away and there is no need to show the notification. If the user launches the app and has an active feedback notification, it would be nice to show the feedback dialog and cancel the active notification.
Receive the notification while the app is in the foreground
UNUserNotificationCenterDelegate
has function userNotificationCenter(_:willPresent:withCompletionHandler:)
, where you decide how to handle incoming notification while in foreground. In our case, we want to check the notification type and also verify the applicationState just to be sure we’re in the foreground.
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
switch (notification.notificationType, UIApplication.shared.applicationState) {
case (.feedback, .active):
// Handle the notification here
completionHandler([])
default:
completionHandler([.alert, .sound])
}
}
App launch with an active notification
We can use the getDeliveredNotifications
function on an UNUserNotificationCenter
to get active notifications, ie. notifications currently displayed to the user. Thus it’s simple to check if there is some active notification we are looking for.
extension UNUserNotificationCenter {
func activeFeedbackNotificationExists(completionHandler: @escaping (Bool) -> Void) {
getDeliveredNotifications { notifications in
let activeFeedbackNotificationExists = notifications.contains(where: {
$0.notificationType == .feedback
})
DispatchQueue.main.async {
completionHandler(activeFeedbackNotificationExists)
}
}
}
}
To cancel the active notification we need to get its identifier
. We get it from the same getDeliveredNotifications
function we used in the last example. Once we have the identifier, we can cancel the notification via removeDeliveredNotifications(withIdentifiers:)
.
extension UNUserNotificationCenter {
func cancelActiveFeedbackNotifications() {
getDeliveredNotifications { notifications in
notifications
.filter {
$0.notificationType == .feedback
}
.forEach { notification in
self.removeDeliveredNotifications(withIdentifiers: [notification.request.identifier])
}
}
}
}
I hope I gave you a new perspective about push notification’s UX. It’s always good to think about outside the box. Yes, you can attach the action to click on the notification, but maybe other ways will make the application more pleasant for your users.