iPhone OS is a closed platform. Daemons (background processes) are not allowed. This means your device (iPhone / iPod) cannot run a user service and communicate with backend servers unless your application is running.
Steve Jobs has been quoted as saying: “You don’t want your phone to be an open platform … you need it to work when you need it to work. Cingular/AT&T does not want their west coast network to go down because some application messed up”. I am not sure how true is that as other platforms have shown otherwise. Bottomline is that lack of background processes (or the restriction for user apps) in iPhone OS seriously limits some app capabilities. This is where Apple push notification service comes in and fills in the gap.
APN (Apple Push Notification) service provides the content provider an ability to invoke an application on the device and/or pass a notification (You can call it “Call for Action”) to it. Though it does not give a device all the capabilities/scenarios that a background process can enable (like prefetching data) but it can surely bridge the gap and enable “Push” messaging scenarios.
Before we understand APNs and how the device, provider and APN Service are bound together, lets pay attention to some terms:
Device: iPhone / iPod
APN Service: Apple’s Push Notification Service that sends notifications to target device(s)
APN: Apple push notifications. APNs are of three types. Sounds, Batches and Text.
Notification Server: Content Provider’s server that sends notifications to Apple’s APN Service to be stored and forwarded to the target device(s)
Token: A unique identifier that is used to uniquely identify a device (It is not the same as Device ID)
X.509 SSL Certificate: Certificate that establishes trust relationship between APN Service and your own notification Server. (APN Service and iPhone already have the trust relationship using a similar SSL Cert)
Please note that “Notification Server” refers to your company’s Content Server (Depending on the need your company may have a single server serving content and notifications or have a multi server deployment) that is tasked with sending notifications to APN Service.
Apple has published extensive docs on APN Service that can be found here.
Lets break the process of enabling push notifications (for your iPhone app) in simple steps (for developers of course):
STEP 1: Setting up the device (Registering the device with with APN Service)
Before you start coding, please ensure you have configured the App ID properly, generated the client SSL Certificate and updated the provisioning profile for the app id (Bundle ID of your iPhone app). Assuming that you or your team lead has already taken care of these steps, you are ready to implement the code patterns.
For your application to listen to push notifications, you need to register with APN Service using “registerForRemoteNotificationTypes” message. The message takes APN types (the types that your app wants to enable) as an argument.
// Register the types that you want to enable
UIRemoteNotificationType enabledTypes = UIRemoteNotificationTypeSounds | UIRemoteNotificationTypeBadges;
Once you have registered for notification types that you want to receive, you will receive two delegate callbacks. One in case of success (this will bring the token that uniquely identifies the device with APN Service) and the other in case of failure (this will bring an NSError).
– (void)application:(UIApplication *) application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token
// Your code goes here: get the token and do something
-(void)application:(UIApplication *) application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
// this will happen only if SSL Cert, Bundle Id, Provisioning profile is wrong, fix these issues and all should be fine
NOTE: You need to run your app on device to test Notifications. Notifications don’t work on Simulator
Besides these two mandatory delegate callbacks there are some other optional callbacks that you may implement in your code. The most commonly implemented scenario is where a notification is received when your application is already running. In this case, the iPhone OS does not do anything other than calling a callback (if you have implemented it) in your app.
– (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
// This delegate callback is called only if your app is running, “userInfo” brings the notification payload.
// Now that you have the notification payload, this gives you a unique opportunity to draw your own custom views and do some housekeeping work …
One more optional message that can be sent to appdelegate is:
This is a message, not a callback and returns all notification types that are enabled for the app
NOTE: This is for Solution Architects: Please be mindful of not using APN Service for any “Guaranteed delivery” scenario as Apple does not guarantee delivery and only the last notification is retained. If you send two notifications to a device back to back and the first one has not been delivered yet, it will be overwritten thereby resulting in a loss of notification.
STEP 2: Share the token with Notification Server (this is “your Server” not APN Service)
Lets recap and revisit the TOKEN. Understanding the TOKEN and where it comes from is crucial to building a three way trust between device, APN Service and your Notification Server. Token is a unique identifier that is assigned to your app via a callback (by iPhone OS which transparently gets it from APN Service).
– (void)application:(UIApplication *) applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token
iPhone OS calls this callback on your app as a result of registration request thereby handing your app a TOKEN (as type NSData). This means your app has successfully registered with APN Service and is ready to receive notifications.
Your app is ready to receive the notifications but that does not mean that notifications are available and your SERVER is READY to send notifications. If your app (on iPhone) has not shared its unique TOKEN with your server, the server has no way of targeting the Notification at your app instance via APN Service. Please note that APN Service is simply a store and forward service that forwards the notification by matching the TOKEN.
So, once the app has successfully registered with APN Service, you need to share this TOKEN with your server. The implementation of how to share the TOKEN is Server specific. Your company may use a REST, SOAP, JSON based interfaces to communicate. What ever the interface, you need to pass on this TOKEN to the Server so that it can target the notification at your app instance.
You can do this in “applicationdidRegisterForRemoteNotificationsWithDeviceToken” callback.
STEP 3: Setting up the TRUST between APN Service and your Notification Server
This step is a server side imperative and will be undertaken by Server side developers. If you are an iPhone developer, you are tasked with implementing the client side functionality. In that case you can assume that server has already been set up for you but if you are one of those unfortunate few who has to manage the certificates, implement the server and write the iPhone app, then you will find rest of the paragraphs useful.
You can implement your server using any Middleware server like Microsoft BizTalk, IBM MQSeries, TIBCO or a custom service written in RUBY, Python, C# or Java. There is a ton of sample code available on Apple dev forums for reference. It is important to understand and accomplish the following:
a). Exchange the SSL Certificates between your Server and APN Service (Please remember SSL Certificates are App specific. Architecture of your Notification Server is totally up to you. You will need to have one SSL Certificate per application)
b). Open a persistant connection with APN Service. It will be a cardinal sin to open/close connections every time a notification is sent to APN Service. Remember threat models and denial of service attacks?
c). Implement a scenario to reopen connections if there is an activity timeout. Android’s service architecture is a very good design pattern that can be used to implement a notification service if you are building a custom service (that acts as a notification server).
d). Implement a Feedback collection service. APN Service has a Feedback service that records events/notifications sent to uninstalled applications. This service can be used in some very interesting ways to know how often the app is being uninstalled.