My last post discussed NSNotificationCenter and Notification Center. I’ll now continue with UILocalNotification and Remote Notifications.
A UILocalNotification is set within an iOS app to trigger at a specific time. During setup, you can specify that an “Open” button be present on the alert presented to the user.
When the UILocalNotification is set up, iOS adds an entry to Notification Center for the app. This entry allows the user to change if a notification message should be displayed, how the notification is displayed (alert message or notification pull down) and what sound plays.
When the trigger time is reached, several things can happen, some of them in sequence:
- If the app is not in the foreground, the notification is sent to Notification Center.
- If the user has enabled alerts for the app, the type of alert selected will be shown. If the app set up the notification to have an “Open” button, the app is launched or brought to the foreground if the user touches the button.
- If the app is not currently launched, it will be and the method application:didFinishLaunchingWithOptions: in the App Delegate is called followed by a call to application:WillEnterForeground: and finally followed by a call to application:didReceiveLocalNotification:.
- If the app is launched but is not in the foreground, it is brought to the foreground and the method application:WillEnterForeground: in the App Delegate is called followed by a call to the method application:didReceiveLocalNotification:.
- If the app is in the foreground, the method application:didReceiveLocalNotification: in the App Delegate is called bypassing any action from Notification Center.
Both methods application:didFinishLaunchingWithOptions: and application:didReceiveLocalNotification: are passed the notification while application:WillEnterForeground: is not.
The method application:didReceiveLocalNotification: should be used to take any actions that are required every time a local notification is received. The method application:didFinishLaunchingWithOptions: can be used to take actions specific to when the app is launched because of receiving a local notification.
Remote notifications, also called Apple Push Notifications (APN), are used to tell an app that something outside the device has occurred. The app can then act on this information. This process requires the action of two remote servers – the Apple Push Notification Server (APNS) and a server maintained by the app developer.
As Remote Notifications originate outside the device, Apple has implemented several security protocols to ensure that only requested and permitted notifications are sent. This makes the setup and sending process significantly more complicated.
The setup process is outlined in the following figure:
- The App is set up via iTunes Connect to support APN. A security certificate and private key (p12) file are generated. Someone must send these to the App Server and the server must retain them, as they’ll be needed to send a remote notification. iTunes Connect also notifies the Apple Push Notification Server (APNS) that push notifications are enabled for this app.
- When the app is launched, requests to register the device and app for APN must be sent to iOS.
- If the user agrees to accept Remote Notifications, the request is forwarded to APNS.
- The Server responds to the device with a token.
- The Device iOS forwards the response to the app.
- The app forwards the token and a user ID to the app server.
Each app using Push Notifications must be set up via iTunes Connect on developer.apple.com. The setup process is fairly complex, but is well documented in several tutorials. The results of the setup include a security certificate, a private key file and notification to the APNS that remote notifications are enabled.
Note that this process must be repeated for each app, and repeated again when the Apple developer credentials are renewed each year. Renew your developer credentials a few weeks before they expire to ensure uninterrupted push notification services to your apps.
Each user must agree to accept Remote Notifications for any app that requests them. Step 2 triggers an alert asking the user to accept remote push notifications. If the user agrees, steps 3 through 6 complete the registration process. During this process, an entry for the app is added to Notification Center, allowing the user to select notification options. If the user declines Remote Notifications, no further action is taken and remote notifications cannot be sent, as the App Server will not have a device token for the device/app.
Sending a notification is a bit simpler:
- App server is told or determines that a notification needs to be sent.
- App server sends message, token, security certificate, and p12 file to APNS .
- APNS verifies information and forwards the message to the device to which the token is registered.
- Notification Center in iOS handles the notification as set by the user.
The actual message payload is in JSON format and is limited to 256 bytes. There are defined fields that contain the message text, define any buttons to show on an alert, set the app badge number and define the sound to play via Notification Center.
As with UILocalNotifications, several things can happen once the notification is received:
- If the app isn’t in the foreground, the notification is sent to Notification Center. Notification Center will read the message and display an alert, play a sound, and/or set the app badge number as permitted by what the user has set and what is in the JSON message payload. Remember that if the device is set to silent, no sound will play.
- If the user has enabled alerts for the app, the type of alert selected for the app will be shown. If the notification defines an “Open” button, the app is launched or brought to the foreground if the user touches the button.
- If the app is not currently open, it is launched and the method application:didFinishLaunchingWithOptions: in the App Delegate is called, followed by a call to applicationWillEnterForeground:, and finally followed by a call to application:didReceiveRemoteNotification:.
- If the app is launched but is not in the foreground, it is brought to the foreground and the method applicationWillEnterForeground: in the App Delegate is called followed by a call to the method application:didReceiveRemoteNotification:.
- If the app is in the foreground, the method application:didReceiveRemoteNotification: in the App Delegate is called bypassing any action from Notification Center.
There are several important details to understand about APN. First, APN is a best effort service. There is no guarantee that remote notifications will be delivered and the APNS does not confirm message delivery. Remember the user can refuse to accept Remote Notifications and can disable notifications for any app in Notification Center.
Message delivery can take up to 30 minutes, even if the device is online. If a device is offline, messages are stored on the APNS for an unspecified time. When a device comes online, the last stored message for each app is sent.
Apple provides an additional server that stores the token used for messages sent with invalid tokens. This server should be queried periodically and invalid tokens removed from the app server database.
Finally, the APN service requires the APNS. If Apple ever decides to stop supporting the server, APN will no longer work.
The three different iOS notifications, NSNotificationCenter, UILocalNotification, and Remote Notifications have very different purposes and implementations. NSNotificationCenter is for communicating events within and on a device. UILocalNotification notifies an app at the time at which a notification has been scheduled. Remote Notifications can inform an app that an external event has occurred.
UILocalNotification and Remote Notifications are handled in a similar fashion. If the app is not in the foreground, Notification Center handles the notification. If the app is in the foreground, there are specific methods in the App Delegate that are called when a notification is received.