651.288.7000 info@intertech.com

Push Notifications Tutorial for iOS 9

by | Oct 6, 2015

push-notification-series

This push notification tutorial post is part of a series written by our developers that documents their journey in a cross-platform mobile app development project. They set out to improve an internal process, create educational content for the developer community, and explore new craft beers and a vintage arcade. Sound interesting? Read more about this series and their efforts in our introductory series post.

 

Here at Intertech, we’re creating a set of native mobile apps to support our Time Entry system. Over the next few months, we’ll be featuring a set of articles to explain how we approached specific features for each supported device (iOS, Android, and Windows Phone), as well as for the Time Entry API server, which handles their requests.  In this article, I’m focusing on the iOS client side of “Push Notifications” (aka “Remote Notifications”) in our Push Notifications series.

Overview & Architecture

Push Notifications are a way to send alerts or “badge” counts (the little number that appears on an app icon) to an individual, or group of iOS users.  Ultimately, these alerts should not be large (iOS 9 has a 2KB limit), nor important, as they might never be successfully delivered. For example, if a user has their device turned off for an extended period, Apple’s Push Notification service (APN) will only store the latest notification sent.  Any previously stored notification is erased by APN after a new one is received.  Even if the device is on, a user may have push notifications disabled on their device.  Due to these “Quality of Service” scenarios, the Apple Local and Remote Notification Programming Guide, states:

Delivery of remote notifications is not guaranteed, so you should not use the notification payload to deliver sensitive data or data that can’t be retrieved by other means.

To that end, we decided to restrict our notifications to a simple reminder that a given week’s time sheet is due.

Push notifications are never sent directly from an application service to a device.  Instead, notifications are sent to the Apple Push Notification Service, which in turn forwards the message to the actual device.  This process involves a few actors:

  • Apple Push Notification service (APN) – Generates device tokens (a unique id for each device that is to receive notifications), and acts as a proxy to send notifications on behalf of an application service.
  • Application Service – The server side component for an app, which assigns APN generated device tokens to a user, and stores them for future message delivery.  The application service sends a notification to a device, by forwarding a message and device token to APN (who, in turn, handles the delivery of the notification).  APN requires the Application Service to have an Apple Generated TLS certificate before it will deliver a push notification to a device.
  • iOS App – Recipient of the notifications.  Code must be invoked every time the app is launched, that asks the user permission for specific notification types (alert, sound, and badge), as well as a device token from APN.  It may sound like overkill to do this upon every launch, however the Apple libraries are optimized to use existing permissions or return a local, non-expired token, when available.

Creating A Certificate

APN requires that the application server has an Apple generated TLS certificate.  If this is missing, or expired, APN will not forward any notifications to the client’s device.  Although this isn’t, strictly speaking, a client side component, the developers of the iOS app are typically the ones who generate and deliver this to the application server team.

There are two types of certificates: development and production.  Until your app has been published as “GA,” you should use the development certificate.  Both certificates can be generated at the “Certificates, Identifiers & Profiles” page (aka iOS Provisioning Portal).

Prior to generating a certificate, you need to create an App ID.  This is also accomplished in the Provisioning Portal.  The App ID must be an “Explicit App ID” (vs. a “Wildcard App ID”), which matches your app’s Bundle Identifier

Inside Xcode:

bunddleid

Inside the Provisioning Portal:

appid2

Also, be sure to enable the Push Notification service in the AppID configuration screen:

enableservices

Next it’s time to create a certificate.  Choose the appropriate development or production certificate (depending on where you’re at with your app), in the Provisioning Portal:

certificates

Follow the wizard – you’ll be asked to choose your App ID, and upload a Certificate Signing Request (instructions on how to generate this file are in the certificate wizard).  Once you have the certificate, pass it on to the application service team, as they’ll need this to connect to APN.

Download the Free eBook: iOS and Android Push Notifications Tutorial

 

Requesting a Device Token

There are two steps that should be executed every time the app is launched: obtain notification permissions from the user and ask APN for a device token.  For the former request, you can specify which of the notifications you need permission for, via the UIUserNotificationSettings constructor.  Simply add .Sound, .Alert, and/or .Badge as seen in the example below (omit the types you’re not interested in).   As mentioned earlier, invoking these requests every launch may seem excessive, though it’s what is expected from your code.  According to the Apple documentation:

  • registerUserNotificationSettings:
    • “If your app displays alerts, play sounds, or badges its icon, you must call this method during your launch cycle to request permission to alert the user in these ways.”
    • “The first time your app launches and calls this method, the system asks the user whether your app should be allowed to deliver notifications and stores the response. Thereafter, the system uses the stored response to determine the actual types of notifications you may use.”
  • registerForRemoteNotifications:
    • “Device tokens can change, so your app needs to re-register every time it is launched,”
    • “If your app has previously registered, calling registerForRemoteNotifications results in the operating system passing the device token to the delegate immediately without incurring additional overhead.”

Here’s our code for invoking both requests:

… the success and failure of the device token request takes place in the AppDelegate.  Since the focus of this blog is detailing push notifications, and not RESTful Web Service requests, I’ve removed the code that uploads the device token to our application service (but don’t worry… those details will be featured in an up and coming post!)  Just note that one of these two methods will be invoked after registerForRemoteNotifications is called… and that didRegisterForRemoteNotificationsWithDeviceToken is where you receive and upload the device token to your application service.

.. although I’ve omitted the RESTful code, here’s an example of how I converted the binary device token to a String format expected by APN.

Receiving a Push Notification

Here are the different notification actions that take place, based on the phone/app state (assuming that the user has permitted notifications for your app, and that the message is not a “silent/background notification” – a silent notification is not seen by the user, but instead causes your app to start running custom code in the background.  A non-silent background notification does the same thing, but the alert is displayed to the user):

table

In order to display a message while the app is in the foreground, implement UIApplicationDelegate’s application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method in your AppDelegate. (NOTE: there is a similar method named application(_:didReceiveRemoteNotification:), however Apple’s documentation recommends using the fetchCompletionHandler method instead.  Also, this method will not be called if the app has been terminated.  Instead, the standard will/didFinishLaunchingWithOptions methods are called).

This method includes an NSDictionary (userInfo) with a nested NSDictionary called “aps.” All of the notification data (including the “alert,” “sound,” and “badge”) is found here.  In addition, there is a callback handler that requires a UIBackgroundFetchResult value (“Failed,” “NewData,” “NoData”).  The first two values are used when the notification triggers an app to download new data.  Since we’re not fetching any new data (we’re simply displaying a reminder to the user), we return “NoData.”

This didReceiveRemoteNotification method may also be called if a “silent/background” notification is received. As such, you should also enable “Background Modes: Remote Notifications” in the target capabilities panel (or else you’ll see warnings in the console).

background

What’s Next?

Now that the app is configured to receive and display push notifications, the application service can deliver messages to a device.  Check out the “Push Notifications Tutorial: Node.js and Azure Setup” companion article for those details.

Looking for training in mobile development? Check out the mobile development courses that we have available!

Intertech also provides Mobile Development Consulting. From Android to iPhone to Windows phone, we can help you build the app that your company needs.

 

More Push Notification tutorials in this series:

Follow Us

Categories

iOS Consulting
Free eBook: iOS and Android Push Notifications Tutorial
iOS Course Finder
iOS Training

Like What You've Read?

Subscribe to the Blog.

Every Friday we send that week's content from our Developers via email. Try it out!

Some ad blockers can block the form below.

You have Successfully Subscribed!

Pin It on Pinterest

Share This