As stated in our previous post, we are implementing push notifications for Android and iOS devices. In this article, we will describe how the APNS works. We will also share some tips for server side development as well as when creating an iOS app for testing.
Quick intro
APNS is the acronym of Apple Push Notifications Service, a service for pushing messages to mobile devices (iOS 3.0+) and Macs (Mac OS X 10.7+). The service was created to provide a way to notify users about important events, even when the application is not running. This is a common scenario since “only one application can be active in the foreground at any time”.
APNS is not designed for sending lots of data via messages, but rather for notifying the client that there is new data available on the server. It gives no guarantees about delivering the messages: APNS server will only store the latest message, overwriting the previous one. Apple specifies different types of notifications, some of which will show up only if the application is not running. This service can only be tested using real devices registered at the dev center.
Apple provides a quick architectural overview of APNS to understand how it works.
APNS is free of charge.
APNS terms
- development certificate: a SSL certificate that identifies you as developer.
- appId: allows an application to communicate with APNS. It is also used to communicate with external hardware accessories, share keychain data between a suite of apps and share data between apps using iCloud.
- provisioning profile: signed xml file; puts together information contained at a specific moment in time by a developer certificate, an appId and multiple registered devices. It does not reference the appId. This means that if you change APNS settings on the appId after creating the provisioning profile, you’ll have to create a new profile with the new appId version.
APNS actors
Sending a notification through APNS involves three actors: APNS, a third party server, and the mobile app. These are the main tasks performed by these actors.
- APNS - Apple:
- verifies the sender is authorized to send APNS notifications.
- verifies the deviceToken corresponds to a registered device.
- stores the message until it can send it to the device or until a new message arrives (APNS only keeps one notification per application on a given device). This responsibility corresponds to a Quality of Service component.
- provides feedback about devices which have uninstalled an application. This responsibility is delegated to an APNS component called Feedback Service.
- sends the message to the device.
- Third Party Server:
- sends a push request to APNS providing message, notification type (alert, badge or sound), deviceToken and sender credentials.
- saves the deviceToken for sending the required messages to APNS.
- handles errors. Feedback should be taken from message responses, the feedback service (lists devices no longer using the app) or from authentication or connection issues that occur when creating the connection to the server.
- Mobile App:
- requests a deviceToken to APNS each time the app is started. By doing this, APNS knows that the app is being used on the device.
- sends the deviceToken to the server.
Here’s a sequence diagram of the basic process.
Some quick tips
- For you server implementation, the connection against the APNS server should remain open, ideally along the whole server application lifecycle. If the connection is reopened too frequently, the sender may be blacklisted, since APNs may consider connections that are rapidly and repeatedly established and torn down as a denial-of-service attack.
- It is a best practice to consume the feedback stream from Apple Push Notification Servers occasionally. Apache Camel APNS component, defaults to once per hour.
- “An application should register every time it launches and give its provider the current token. […] Moreover, never cache a device token and give that to your provider; always get the token from the system whenever you need it.”
- Device token uniquely identifies a device. Should be stored on server side to enable us send messages targeted to it. If we get feedback from the feedback service about a device no longer using the app, we should remove its token from server.
Common issues when developing an iOS app for testing
During the process of building the mobile app for testing the APNS integration, we found several issues. These issues were very similar to what most developers faced. Here are some examples:
- “ERROR CODE -1202 = The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xx.xx.xxx.xxx” which could put your confidential information at risk.”
- “2012-02-16 15:58:59.813 appName [819:307] Connection failed! Error - no valid ‘aps-environment’ entitlement string found for application (null)”
- If you get this error message, you should create an Entitlements.plist file by adding the key aps-environment with the corresponding value (development/production, depending on the mode you want to run the app). To do so, go to the root of the project, select New File -> Code Signing -> iOS -> Entitlements. When created, add a String entry with the corresponding key and value. This should fix the issue.
- “The entitlements specified in your application’s Code Signing Entitlements file do not match those specified in your provisioning profile.”
- This error means that the provisioning profile xml doesn’t have the aps-environment variable setup correctly or its value does not match the AppID configurations. Most likely, you created an AppID, then the profile and then altered AppID preferences (ex.: enabled / disabled apns), so that the latest changes did not make it into the profile xml. Remember that when changing the AppID preferences (enabling/disabling APNS or other services for it), these changes do not propagate to the profile, since the it does not reference an AppID, but codes its information to the xml and no “refresh profile” option is provided to change profiles content once created. If changing the AppID preferences, create and install a new profile (editing the xml won’t work since the file is signed: you’ll just make it unusable and need to restore it or download a fresh copy). See that its aps-environment value will be development/production, depending on the selected options when enabling APNS.
Some useful links
- Apple Push Notification Service: general APNS documentation.
- Libraries? If working with Java, check javapns and java-apns. If you are using Apache Camel, you may be interested on their APNS component