Why do we care about Notifications?
Notifications are an essential part of the mobile ecosystem. One of the main reasons why businesses build mobile applications is to utilize push notifications to connect their users to their apps. A great push notification campaign can not only drive user’s to their app, but continue to retain them.
In this article we are going to see how we can use local notifications to build location based notifications, even when the app is in the background.
A Real World Example
Presenting a notification when a user is near a certain location can be very useful for many companies. I recently worked on a project where the goal was to present a notification when a user is close to one of their specific locations. When the user taps the notification, it will present a QR code view controller specific to that location.
Engineering Thought Process
When trying to solve a problem I try to see what tools are already available before going off and building something custom. Here are a few options that I explored:
Push Notifications Vendor
Since the project was using Urban Airship as a push notifications vendor, I thought that they might have the functionality to send a push notification based on a user’s location. As it turns out Urban Airship doesn’t support this kind of functionality, so I needed to explore another option.
Since showing a QR Code was the ultimate goal, I thought using PassKit was another option that could work. Airline applications use PassKit to allow users to add their boarding pass to their Apple Wallet.
Implementing PassKit for this use case would be complex, involving the need for backend API work to be done. Although this option would satisfy the requirements, it was ultimately not chosen because of the amount of work needed to integrate it.
If you’re interested in learning more about Apple’s PassKit, you can find more information about it here:
Wallet Developer Guide: Introducing Wallet
Explains how to define and update passes, and how to prompt users to add passes to their library.
Leave a comment if you’d like to see a future article about adding a custom pass to wallet.
After much research, I came across UNNotificationTriggers which according to Apple is:
“An abstract class for representing an event that triggers the delivery of a notification.”
Fortunately for us, Apple provides a trigger for location so that a notification can be fired when a user enters a specified region. They also offer triggers based on time, calendar and push notifications.
Utilizing the UNLocationNotificationTrigger, a local notification can be scheduled and triggered when the user enters a specified region.
Next, let’s take a look at how to setup an app to receive a location triggered notification.
1. Privacy First
In order to use a location based trigger, the user will need to give the app permission to use the device’s location. A privacy description will need to be added to the Info.plist.
Add the following key to the Info.plist:
The value can be any description that explains why the user’s location is needed. If these keys are not added to the Info.plist, the application will not prompt to ask the user for location permissions.
Keeping our code neat
To help with the rest of the article, the
LocationNotificationScheduler was created, as shown below, to help with the scheduling of our notifications. For the next step let’s focus on the
requestNotification public function.
2. Ask for location permissions
Next we need to ask the user for permission to use their location. The current location authorization status can be found by calling
Before the app asks the user for location permission, the authorization status is “not determined”. To ask for the first time, the
requestWhenInUseAuthorization is called on the location manager. The reason why the app only needs to call “when in use” authorization is best described by Apple:
“Because the system actually monitors the regions, you don’t need to request always permissions for your app.”
Apps that don’t ask to always use a user’s location, ultimately protect the user from the misuse of their location.
AuthorizedWhenInUse / Authorized
At this stage, the user has already granted the app permission to use their location. The next step is to ensure the user gave the app permission to present notifications.
Restricted / Denied
If the user already restricted the app to use the location, the delegate
locationPermissionDenied() function is called to handle this case. In the example app, we decided to prompt the user to go to settings, so that they can enable location. Its good practice to provide this prompt as it makes it simpler for the user to remove any restrictions in the future.
2. Ask for notification permissions
After gaining permission to use the user’s location, the next step is to ask the user for permission to send a local notification.
As shown in the image above, we can request permission from the
UNUserNotificationCenter.current().requestAuthorization() function. The status of the authorization can be checked in the completion block. If there’s an error, we call the delegate function
notificationPermissionDenied to let the delegate know that the permission request failed.
3. Create the Local Notification & Region
Now that all of the permissions are out of the way, it’s time to focus on the notification itself. In order to setup a location notification trigger, a
UNMutableNotificationContent and a
CLCircularRegion object will be needed. In the sample functions shown below, they take in a
LocationNotificationInfo object that is used to consolidate all of the properties needed for the notification.
The title and body of the
UNMutableNotificationContent is set here with the information from the
LocationNotificationInfo object. If there is a need to send metadata with the notification, it can be set to the
CLCircularRegion is created with a center point (coordinates), a radius (meters) and a unique location identifier.
The center point that’s needed for the
CLCircularRegion is a
CLLocationCoordinate2D object that describes the latitude and logitude of the center of the circular region. These coordinates can be hardcoded to a specific location or integrated with Apple Maps or Google Maps to allow the user to specify the center location.
Once initialized, the the property
notifyOnEntry is set as
true to allow the notification to be triggered when the user enters the region. It’s also recommended to set the
false so that the user isn’t notified when they leave leave the region.
4. Add request to notification center
UNLocationNotificationTrigger can be instantiated with the region that was created in the section above.
With all the pieces ready, we can finally put it all together. A
UNNotificationRequest needs to be created with a unique identifier, notification, and trigger.
UNNotificationRequest can be added to the
UNUserNotificationCenter with the optional completion block to capture any errors.
*As a side note, adding a request to the
UNNotificationCenterwill happen in the background, so be sure to run anything that interacts with the UI on the main thread.
5. Test using the simulator
In order to test out the location trigger, I created a example project called LocationNotifier. It’s a simple application that will allow the user to schedule a notification to be triggered when they are near the Brooklyn Promenade. If you’re in NYC, definitely recommend you check it out, its one of my favorite places in the city. You can also change the coordinates in the
ViewController class to be anywhere you’d like.
Here’s a sample video on how I was able to change the location of the simulator to test the location trigger.
Why is this important?
Location tracking on iOS can be tricky, however privacy and security is of the utmost concern for most companies. With the notification triggers, Apple was able to provide developers location functionality without the need to expose the user’s exact location information. Which if you think about it, makes sense, why does the developer need the user’s exact location just to present a notification if they are in a general region? Providing this functionality not only makes it easier for developers to implement, but also protects users!
Thanks for reading! 🙌
If you have any questions, comments or requests for future articles please leave a comment below!