Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2009-120
$eventId
ID of event: wwdc2009
$eventContentId
ID of session without event part: 120
$eventShortId
Shortened ID of event: wwdc09
$year
Year of session: 2009
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2009] [Session 120] Apple Push ...

WWDC09 • Session 120

Apple Push Notification Service

iPhone • 57:43

The Apple Push Notification service provides a way to alert your users to new information, even when your application isn't running. Send text notifications, trigger audible alerts, or add a numbered badge to your application icon. Learn best practices for optimal performance, consistency, and user experience.

Speakers: Chris Marcellino, Kris Macleod Bell, Justin Santamaria

Unlisted on Apple Developer site

Downloads from Apple

SD Video (177.9 MB)

Transcript

This transcript has potential transcription errors. We are working on an improved version.

Hi, I'm Chris Marcellino, an iPhone Software Engineer and I'm here today to talk about the Apple Push Notification Service. But before we get started I'm curious, how many of you are familiar with the new version of the Push Service by a show of hands? Oh wow, OK, great.

Well, for those of you that raised your hand, I'm going to cover some best practices and some advanced troubleshooting tips for you. But for the rest of you, before the end of this hour you'll know everything that you need to know to start sending notifications across the service.

So let's get started. So today we're going to talk about how you can make your apps network connected even when they're not running. Now this is huge because this is going to give your apps a whole new angle in the app store. We're also going to talk about how you can get users the information they want when they want it and let them know that there is more waiting for them. And finally we're going to do all this while minimizing the impact on battery life.

So in this presentation we're going to cover the basics on how to push sounds, badges, and alerts across the service, server protocols and certificates, as well as some best practices and some advanced troubleshooting techniques. So on the logistical side this service works both over cell and WiFi connections and it's available free to any member of the iPhone Development Program. Now this is huge, you don't need to deal with carriers, you don't need to get any advanced certifications.

Right out of the box you can start sending notifications across the service. And finally, using this service is incredibly easy. All of you are going to be able to send notifications to iPhones. So let's cover some background. iPhone OS 3.0 maintains one persisting connection from the device to the Apple Push Notification Service and this single connection is used by all applications on the iPhone to receive notifications from the service. This centralized design preserves battery life as well as maximizes the performance of the Apple Push Notification Service. To start using this service you're going to need a few things.

First you're going to need a server. Now it's important to understand the notifications that are sent from a service that is external to the service and is simply passed through the service down to the iPhone. Next, you're going to need a certificate that uniquely identifies your application to the service. And finally you'll need a new provisioning profile that test your applications on the iPhone when you're debugging them and developing them So once you have all these things, you can start sending notifications across the service.

Doing so involves four simple steps. So first your iPhone application on the iPhone needs to tell iPhone OS that you wish to start receiving notifications from the service. It does this by using UIKit API that in turn tells the Apple Push Notification Service that a given instance of your application on a specific device wishes to receive notifications. Second, once you've successfully registered your application receives something back that's called the device token which uniquely identifies your device to the service. You then communicate this token to your server where your server associate this token with the unique user of your application.

Later you'll use this token to start sending notifications to the service. Step 3, your server sends those notifications using that device token. And finally step 4, iPhone OS receives those notifications, displays the sounds, badges, and alerts that you send in the notification payload on the iPhone OS. So let's look at step 1 in detail.

[ Pause ]

So step 1 is pretty simple, use the UIKit API on the device in your application, tell iPhone OS that you want to register for notifications. To do this step all you need to do is call UIApplication registerForRemoteNotificationTypes passing the types of notifications that you wish to receive on the device. Once you've done this step you will receive one of two different delegate callbacks. The first if you succeed is UIApplicationDelegate application didRegisterForRemoteNotificationsWithDeviceToken.

Now you get back that opaque device token, an NS data that uniquely identifies the current device to the Apple Push Notification Service. But if you fail you'll get UIApplicationDelegate application didFailToRegisterForRemoteNotificationsWithError. In this case it will only happen if you have provisioning profile troubles or bad entitlements, or if you're using the iPhone Simulator because we don't have support for the Push Notification Service in the Simulator. So just fix whatever is wrong with your provisioning profile entitlements, reregister and you'll get back the first callback.

So once you've succeeded and got that device token, as I mentioned this device token is a unique identifier which identifies the current device to the Apple Push Notification Service. But one thing to note, if it is distinct from UIDevice deviceIdentifier because unlike the deviceIdentifier the Apple Push Notification Service device token gets erased whenever the device is wiped for security reasons. And finally if you don't have the token and memory just use the registration API to get the token.

There is no cost in calling the registration API. Call as many times as you want. Don't store it in your documents or preferences because we don't want it getting out of date with what the iPhone OS has for the device token. There's a couple other optional delegates and callbacks you might want to implement.

The first is UIApplicationDelegate application:didReceiveRemoteNotification. Now you'll use this notification if you want to receive notifications when your application is already running since if your app is already running, iPhone OS does nothing for these notifications. Instead use these callbacks to get that payload that you sent and display some type of UI to let the users know that notification was received. Also we have a method as opposed to a delegate callback called UIApplication enabledRemoteNotificationTypes which is a method to let you see what types of notifications the user has elected to receive in the centralized settings. We'll talk about both of these more in depth later in the presentation.

[ Pause ]

So at step 2, you take that device token that you got after registering and you send it to your server where at your server, you associate it with a specific user of your application because you'll later going to need that token to send notifications to the service. Now one very important thing about step 2 is that step 2 is completely up to you. iPhone OS does no part of this step for you so using whatever means you want, send this token to your server.

That's all there is for step 2. Now at step 3, this is where it gets interesting. Step 3 is where you start sending notifications from your server to the Apple Push Notification Service. But before we talk about how to send notifications, I want to make sure that everyone here is familiar with what JSON is. So JSON as many of you know is short for JavaScript Object Notation but you don't need to know or write any JavaScript to use the push notification service.

So it's a Java-- it's an object notation that derives from JavaScript but it's also a human readable, compact in architectural neutral way to represent Cocoa property lists such as NSDatas, NSStrings, NSDictionaries, and NSNumbers. We're going to be using JSON payloads to represent the payloads that we sent across the push notification service. So here is a typical JSON payload. As I mentioned it needs to be strict JSON but also Apple Push Notification Service device tokens are limited to 256 bytes per notification.

So at the top level of this dictionary there is a dictionary called aps. This contains the alert, badge, and sounds keys that iPhone OS displays on behalf of your application when your application is not running. Outside of this dictionary is reserved for your app, put whatever keys you want in there as long as they are valid JSON and under the 256 byte limit.

So let's look at these keys in depth. The badge key is an integer value in the JSON APS dictionary. When you pass a badge you'll see on your applications icon on the home screen the red badge that are used when getting unread mail. This is the same as the UIApplication application icon badge number property that you've used in iPhone OS 2.0. So if you pass a positive number here, it will display a badge on your applications icon. But if you pass any other type of value or omit the value entirely from the dictionary, will remove the badge from your applications icon.

The sound key is a string value which is one of two things. Either it's the name of the file in your applications bundle or it's the system wide reserved key default which they're non-configurable default sound. If you choose to put a sound file in your applications bundle it needs to be of a supported format.

Those formats are only linear PCM, MA4, uLaw and aLaw but not MP3, AAC or other perceptual encoding formats since we don't want to interrupt music playback if the user is already listening to music. We also handle vibration automatically. If the ringer switch on the device is set to vibrate we'll simply vibrate the device any time we see a sound key at all.

So alerts can be either strings or dictionaries but the most common format we expect to see are strings. We'll take the string you pass for alert and use it to create the body of an alert message on the iPhone home screen, or if your phone is locked in the slide to unlock screen. But as I mentioned there is also a dictionary format which can be used to localize either the alert body or the View button.

So if you pass the loc-key or loc-args keys in your JSON payload, we'll look up the loc-key value in your applications Localizable.strings file in your apps bundle. That way you can pass a value in a specific language for each language that you support and we'll look at that key, substituting the loc-args key into that string to display a localized alert. For example, if in your Spanish Localizable.strings file you have this string, we'll substitute in "Jen" and "iPhone" to create this alert.

So we do this substitution the same way that you do it both on the Mac and on the rest of iPhone OS using NSLocalizedString and NSString stringWithFormat. That is arguments can be ordered by localizers using the same macros that you're used to and we use the current system language to choose the right Localizable.strings file out of your apps bundle.

If you're new to localizing strings, check out the rest of our resources that we have online and the other sessions we have on localization because a lot of these concepts are shared. Also, one thing to note is that since you're sending in this case the localized string key as opposed to the value across the wire, you want to keep your localized string key short 'cause that's what counts against your 256 byte per notiVfication size limit.

As I mentioned you can also customize the View button but we refer to the View button as the Action button because tapping that button takes some type of action such as launching your application. So if you pass the key, action-loc-key in your JSON dictionary inside the alert dictionary, will display whatever the value that Localizable.string key is in your current language as the View button on the iPhone OS. So say PLAY_KEY maps the Play in the current language which is English, you will see this alert instead. But say you are sending notification alerts that are strictly informative and there is no action to be taken at all, and you just want to remove the View button.

You can do that by passing the JSON primitive null, which looks like this, as the action-loc-key inside your alert dictionary and you will get this as a result. So here's a typical JSON payload, it weighs at 150 bytes, pretty standard, all the keys you expect to see in a normal notification message, even some custom app data.

But by changing our JSON emitter or by simply stripping the whitespace after we've output the JSON, we can bring this payload down to 96 bytes, which is over a 50 percent improvement in space savings. Now stripping the whitespace helps go a long way towards avoiding those per notification size limits in almost every case so we really recommend that you do this. So that concludes the device side of step 3, sending notifications.

Here to talk about the server side is my partner in crime, Kris Bell. Thank you.

[ Applause ]

Good afternoon everybody my name is Kris Bell. And for the next 25 minutes I'm going to lead you through the Apple Push Notification Service from the perspective of the server itself. So if you are wondering why SSL certificates are important to the service or perhaps you are wondering if it's cool to have multiple concurrent connection open to the service at the same time, great because that's what I'm going to talk about.

There's a couple of assumptions that I'm going to make. First assumption is that as developers you guys know how to get your application on to the iPhone. And based on the APIs that Chris Marcellino just talked about, you know how to get the token from that device, send it to your content server to register the device. Now, making those assumptions there are two things you're going to need in order to be able to talk to the service. The first one is you will need an X.509 SSL certificate. You get this from the iPhone Developer Program portal.

If you have one application, you will have one SSL certificate. If you have five applications, you will have five SSL certificates. There is a one-to-one relationship between an application and an SSL certificate. Chris Marcellino just described the message payload, it's a JSON payload, and I'm going to talk a little bit about that as we go through and point out some highlights. So why is an SSL certificate important to the service? Well, it represents your service identity.

It's unique to your application. It establishes trust between you as a developer and Apple, so you should keep it safe. For example, let's suppose that I'm a developer and have an application and I have myself a service identity. Perhaps it would be unwise of me to give my service identity to my scheming and brooding 13-year-old nephew who has got an unhealthy appetite for hacking into systems.

Probably it will be also unwise for me to take my SSL certificate on a little memory stick here and take it down to the local pub with me, leave it on the counter after a couple of drinks. The reason why it would be unwise to do so is the following. Apple reserves the right to revoke certificates that are being used to abuse the service, so keep your own safe.

Now as Chris described the message payloads are JSON and there's a 256 byte maximum. I'm going to tell you in a moment or two what happens when you go across, when you go above that limit. What I'd like to point out with this particular slide is that you should avoid embedding sensitive user information in your payload. It seems obvious but don't put social security numbers inside your message payloads and like this slide here, don't put credit card numbers in the payloads.

It's just not a good idea.

[ Pause ]

So let's talk about how the service actually operates. To do so, I'd like to illustrate with what I think is a killer application for the iPhone. Let me describe that to you. So you have an iPhone here and when you touch the screen in various discreet points and at the same time you blow into the microphone, the iPhone emits a whole series of yelps, yowls, yarrs, grunts, burps, belches. It's awesome, it's a great application right, it's called iGrunt. All my friends love it, they think it's fantastic.

Chris Marcellino has it installed on his phone too, great stuff. My dilemma though is that I don't know how to make it better for version 2? Well one thing I could do is to enable push notifications. And by doing so I could send a message to Chris Marcellino, perhaps a really loud burp, when I know for a fact that he is in an important meeting with Scott Forstall or perhaps he is having dinner with his girlfriend's parents or something like that. That will be great.

I should point out that this is perhaps the most, perhaps not the most valid use of this service but it's fun. OK, so the first thing that I would need to do, I would need to update my application with the APIs that Chris Marcellino described. The second thing I need to do is to get an SSL certificate from the iPhone Developer Program portal. And once I have my certificate from the portal it is out of the picture, it's gone at that point, don't have to worry about it anymore.

So then I exchange my SSL certificate with the Apple Push Notification Service and I establish a secure SSL connection between my server, my iGrunt server and the Apple Push Notification Service. Now the phone, the iPhone OS 3.0 also has an appropriate SSL certificate for the Push Notification Service. So that when Chris Marcellino turns his phone on it also exchanges certificates with the Apple Push Notification Service and establishes a secure SSL connection. Great, now at that point my iGrunt server can start sending messages to Chris' phone.

This is where the interesting thing happens. How does the phone now which application to associate with the particular message that just came in? Well we talked a little bit earlier about how there's a one-to-one relationship between an application and an SSL certificate. There's this little bit of information that's shared between the application and the certificate and that information is called a bundle ID. There is a unique bundle ID for every application on the phone.

[ Pause ]

So you have your certificate, what happens next? Well you need to open up an SSL connection to the service as I just described. The easiest way to do that is to get up on to the developer forums and check out all the example code that those guys have written. It's fantastic.

Developer forum has been just wonderful. The guys up there, they've been writing examples of how to do this in all kinds of languages. There are examples in Ruby, in Python, and Perl, in C#, Java, you name it. There are examples up there in all kinds of language. Get on-line, check it out, it's awesome.

You can also establish multiple connections to the service at the same time if you wish. Now, why would you want to do that? Well, let's suppose for a moment you're a big content provider. You have a big cluster of machines, 30, 40, 50, 100 machines, whatever it is. It would be inconvenient if each of those machines in the cluster had to share a single connection to the service. So if you have a service you have a content provision in service like that, by all means, open up multiple connections to the service.

It's not a problem. However, if you just have the one server, you really only need one connection. And the reason for that is that a single connection is more than capable of consuming all of your uplink bandwidth to the Apple Push Notification Service, it's very efficient. Whether you have one connection open to the service or whether you have 50 connections open to the service, the important thing to do is make sure you keep those connections open at all times.

And we'll talk about that a little more in a moment. So then the next step is to construct your message in the fashion that Chris described earlier and then you send it over your open connection, construct another message and send it over to that connection. It's really straightforward. Let's talk about those persistent connections and why you should keep them open.

Well, the worst thing that you could do to the service is to open up just one connection, send one message on it and then close the connection again. That would be bad and could be mistaken for a denial of service type. So keep those connections open. Now it is possible that the Apple Push Notification Service might actually sever your connection instead. When would that happen? Well let's suppose that you sent a completely bogus token to the service. Well, it would cut your connection right at that point.

It's a good indication to you that something went wrong. Also, if you send a message payload that is greater than that 256 byte limit, Apple Push Notification Service will sever your connection. That's an indication that something is wrong. Now check that, fix it, and open up the connections again. There are a couple of exceptions here.

Let's suppose that you're maintaining persistent connections but you just haven't sent anything over the wire for an extended period of time, say 2 hours or whatever. It is possible you could get a TCP/IP timer and that would also cut your connection. If that happens then don't worry about it. Just open up another connection as necessary and keep the connection open.

Let's talk for a minute about the protocol itself. It's a binary protocol. It's very, very high throughput and low overhead which is great for your servers because it means that they're used most-- your uplink is used most efficiently. There's also a streaming protocol. And what that means primarily is that you do not get a response for every- and each message that you send to the service. It's very simple format so let's take a look at that now.

It starts off with the 0 byte header. The next field of interest is the device token. That is the device that you are going to send a message to. And the last field up there is the actual JSON payload. It's a very short one we see up there. The second field and sorry, I beg your pardon. The third field and the fifth fields are prefixed with a 2-byte length field.

It's very straightforward. Now let's suppose for a minute that Chris Marcellino really is having dinner with his girlfriend's parents and he's turned his phone off because he doesn't want to get any messages from me. What happens when I send messages to him at that point? Well, the Apple Push Notification Service has the store and forward redelivery mechanism and there are a couple of things that I'd like to press with regards to that.

The first thing is the store and forward mechanism stores just one message per application. So if my iGrunt application sends two messages to Chris' phone and his phone is offline, only that second message will be retained and subsequently sent to his phone when it comes back online. However, if Chris' phone is offline for an extended period of time, it is possible that both of those messages that I sent to him will expire.

Another thing that I'd like to press home about redelivery service is that it is a best attempt delivery. It's just like SMS in that regard. And what that really means is that if there's a huge earthquake and a bunch of hard drives are swallowed up into this great big hole in the ground then some of those messages probably won't get delivered.

[ Pause ]

So let's just imagine for a moment that for some unfathomable reason Chris Marcellino uninstalls my iGrunt application. What happens when I start to send messages to him? Well, sadly, I-- the application, my iGrunt application can't call home and unregister at the time when it's actually uninstalled because the phone may be in airplane mode or out of service range.

So what do we do? The Apple Push Notification Service has a feedback mechanism that records events when messages are sent to uninstalled applications. So you should call this on a regular basis, let's say once a day or more often and it operates just like-- it operates in the same fashion as when you're going to-- as when you're going to send messages. So you connect to it with the same SSL certificate as you do when you're going to send messages.

The distinction is that you connect to a different host. Another distinction is that as soon as you initiate the connection, the feedback service starts sending data back to you in the form of binary records. When it's finished, it will sever the connection. That's an indication to you of course that there is no more data. Let's take a look at that right now. The first 4 bytes represent a UNIX timestamp. That is the number of seconds since 1970.

It is anchored to UTC time zone. The third field represents the device token. This is the device upon which your application has been uninstalled. You should no longer send messages to that device. It's also prefixed with a 2-byte length field. Now it's quite possible that you query the service, the feedback service, and you get no responses at all. Well, great.

That means that nobody has uninstalled your application since the last time you queried the service. OK, now I'm sure some of you in the audience probably have some questions about the scalability of the service. Maybe you're wondering how many messages you can send to it over a period of time.

Well I'd like to try to address that with a short video. Now it's not necessarily easy to demonstrate a backend server. So what we try to do is to get-- give it a face. And the face that we've given this backend service is in the form of what you see on the screen. In fact, there are actually three applications running here. The first application represents millions or sorry an emulation of millions and millions and millions of virtual devices.

There's virtual iPhones, virtual iPod Touches. The second application represents thousands of developers like yourselves sending hundreds and thousands of messages to the service.

So let's play that and take a look at what it does. Now as a message is sent to a particular device, this third application picks up that message and represents it as a different color on a particular cube and then that cube fades away overtime. So what you're seeing is a bunch of blinking devices as they're receiving messages. This is a zoomable application So as you see as we zoom out of it, you can see more and more devices.

In fact, if we zoom all the way out, this rendering starts to take on a more solid form because there are just so many virtual devices in there. There's actually about 10 million virtual devices represented there. And it's on the order of a million messages per second being sent to the service.

Now if you as a developer have been using the production system to send messages for the last few weeks, then you've been competing with not just one of these emulations but several of them running currently. So you've been competing for the attention of the service with tens of millions of devices and millions of messages per second. Now demos are great but the important thing is not necessarily the demo itself but this critical aspect.

There are no bottlenecks in the Apple Push Notification Service. It is-- it has the characteristics of linear scalability and what that means to you as developers is that as more and more devices are added overtime as the service matures, more and more people start using it and more and more messages are sent to the system, you don't have to worry about the performance characteristics degrading overtime.

So with that, I'd like to go through four things that I'd like you to take away from this segment of the presentation. The first, of course, is please maintain persistent connections. Don't open up a connection, send one message, and close it. That would be bad. At some point, somebody would probably uninstall your application. Please check the feedback service on a regular basis daily and check to see if there are any devices to which you should no longer send messages.

Thirdly, don't send sensitive information, sensitive user information in your payloads. Don't send social security numbers, credit card numbers, and so on. Last but not least, protect your service identity. It is your responsibility to ensure that your service identity is not abused by somebody else. That concludes the section of the presentation.

I'd like now to hand you back to Chris Marcellino. Thank you.

[ Applause ]

So Kris just covered the server half of step 3, sending notifications. So let's talk about step 4. Step 4 is where iPhone OS receives these notifications from the service and displays the badges, alerts, and sounds that you send your notification payload. So the most important thing to note here is that iPhone OS does nothing with the notification if your application is already running. This is important.

If your app is already running, you're just going to get the UIApplicationDelegate application didReceiveRemoteNotification callback, you should handle-- implement this callback and handle it when you receive notification so that your UI gets updated and gives you some contacts of the notification that was just received. If you need to update your badge, do so using the UIApplication application:iconBadgeNumberProperty because iPhone OS isn't going to do this for you.

Also, play new sounds if you need to 'cause again, the notification is not processed by the OS But if your app isn't running and you send an alert in your notification payload and then the user tabs view on that alert, iPhone OS will launch your application and call one of these two delegate callbacks to give your application the payload.

But first, if you implement it, it's application:didFinishLaunchingWithOptions, you'll get the notification payload in the options dictionary where then you should use it to bring the user to the part of your application that corresponds with the alert that they just tab viewed on since you really want to give them some continuity from the alert all the way into your application.

Second, if you don't implement that after your application has finished launching, we'll call application:didReceiveRemoteNotification just to give you the alert anyway we can. So as Kris mentioned the store and forward redelivery system in the Apple Push Notification Service stores at most one notification per application. What this means to you when receiving notifications is that all of your notification should have the complete state because earlier notifications that you send in a series may be overwritten on the service.

So don't send a badge then later send an alert and expect the badge to always be received because it might have been overwritten if the device was offline. In send, in every alert you send be sure to send the current badge in every notification and any alert if you still want them to be displayed. Don't assume that iPhone OS will keep your badges around in that case.

For the same reason though, iPhone OS has to assume that older messages are now obsolete so what it does to help you is it clears any badges and alerts any time it receives a notification without an alert or badge key so it has to assume that notifications may have been dropped in the meantime and that those are now stale. This is the same reason that you can't increment and decrement badges 'cause we don't want to rely on every notification being received and you being off by one. So the take home point here is just send in every notification the complete state your app has.

We also have some Centralized Settings in the Settings application on the iPhone which helps you control a few things. The first is we have a master switch which let you disable notifications system-wide to save battery power, for example. And secondly, we have per-applications settings to control sounds, alerts, and badge occasions on-- and badges on ?FYI basis.

So the switches that you see here though only reflect what types of notifications that your app elected to receive at registration time using the UIKit API. So be sure to pass the right types when you register 'cause we want the settings to reflect what your apps are actually capable of to a user. So let's spend some time to talk about user experience.

I know this is going to be an important issue with push notifications. It's key to note that alerts are perhaps the most intrusive type of notification you can send, so whenever it's appropriate, please send badges and sounds instead. So let's look at each of these types in detail.

Badges, we expect to be the most popular type of notification that's send across the service. We think you should use badges for any type of actionable information that you have like new unread messages, new friend requests, maybe new status alerts or if you have a business app, maybe business action items or something.

And because you're doing all of these when your app isn't running, you need to keep a server-side count of the types, the number of action items that you want to display in the iPhone OS. Now this is where it gets interesting 'cause it's-- generally speaking, you want your app to be able to work offline if that's something you support, but you might also have external source of information so you need a handle on your server synchronizing all these sources of truth about the number of remaining action items. So be sure to test your logic here.

[ Pause ]

Sounds are also really important because they give the user context of the notification that was just received without actually looking at their iPhone. It can be in their pocket or in their purse and they'll know exactly what application just sent them a notification. Now, think of all the great applications that have really specific sounds on either Mac or PC that let's you know exactly what application that notification is from.

That's the type of sound we want you to use in your push notification alerts 'cause it lets users know what app just sent them that notification. And to be specific these are generally branded sounds, not really long ringtones or other obnoxious sounds, something that's short and sweet and uniquely identifies your app.

Also, since users might be listening to the iPhone or iPod via headphones or via car stereo, it's really important that you use a CDI or quality sound file. Don't, you know, record in your garage and have your kids running around the background screaming, probably not a good sound file to use.

And finally, alerts. There is definitely some times where you do want to use alerts that are totally appropriate to use alert notifications. For example, alerts that are totally worth knowing like the chess match that you are currently playing is now your turn because your opponent just made a move, or information that you completely need to know like this WWDC presentation just changed rooms.

But just the same there's times when you don't want to use alerts, they're are really bad to be sending alerts to your users, namely, information that you just don't need to know like high scores in video games or other gimmicks, and information that's just strictly too much like spam, advertising, and other nuisances that users don't want to see at all. 'Cause if you send these, users are just going to disable your app, the push notifications for your app in the Centralized Settings or worse, uninstall your application entirely.

So don't bombard them with alerts.

Couple more best practices before we finish up. Since the device might be offline or out of service when you send a notification, and if you send more than one, earlier notifications might be overwritten on the service or the user, worse, might disable notifications for your app and settings. You have to assume that notification service won't deliver every message to your phone. So be sure to connect to your server and pull down whatever information you need when your application launches.

Don't depend on the service sending you a reliable stream of data. Also, every time you connect to your server, be sure to upload that device token so it doesn't get out of sync due to some edge cases involving syncing and backups and restoring. Also, as I mentioned earlier, don't store that device token in your preferences or documents. Get it from the registration API and send it all the way to your server every time you connect.

So I want to also cover some troubleshooting tips. We have a great resource for debugging push notification applications on the iPhone in the iPhone Console. So in Xcode, if you go to Window menu, Organizer, choose the current device that you're using, and then choose the Console tab, you'll see the iPhone Console. Here's where we log all sorts of information, errors related to push notifications like JSON format errors, invalid keys, keys we can't parse, sound format errors, et cetera. So this is a great resource for debugging your application.

I want to give you a couple of examples of errors you might see here. Here's a typical JSON payload, has a badge key and a sound key, but when you send this notification, nothing happens at all in the iPhone. Instead of seeing the badge and hearing the sound, nada.

So, of course, you check the iPhone Console and you see Object value expected for key: aps; Trailing comma disallowed in object. Now, what this means is this spurious comma you left in your JSON payload which makes this invalid JSON syntaxically per the standard. iPhone OS can't parse it. So what I got to do is remove that comma, resend your notification and it starts working again.

You get your badge and your sound, problem solved. So let's look at one more example. Here's another typical JSON payload but this time no trailing comma which give you a badge and branded sound this time. But when you send this notification, you see the badge and you hear a sound but not your branded sound. Instead you hear the system-wide default sound So you look in the iPhone Console and you see this error message. No remote notification alert sound file found for 'soundfileA.aiff'. Playing default sound.

So you look in your application's build directory in your Xcode project, you see the sound file in there, everything looks fine but still no, you know, sound. What you might not know though is that iPhone OS uses a case sensitive file system. So since the case in the notification payload is different from the case of your sound filename in your applications bundle, iPhone OS can't find the sound file.

So simply by correcting the capitalization that matched, your problem is solved and you hear your branded sound file. Couple more troubleshooting tips. So that first error that we looked at is completely avoidable if you use a JSON to create your payload-- sorry, JSON library to create your payloads.

Don't try hard recording at JSON or writing your own JSON emitter because there are so many libraries either free or built-in to the various languages that you are going to use that can do this for you, and having a library to do it is much more future proof and easier to code with and avoid debugging hassles. If you need resources for where to get these JSON libraries, check out JSON.org.

They have tons of information and information about the specs. As I mentioned in the previous slide, use the console for debugging your applications. And finally there's one more thing we have for you today. You may have noticed that when debugging your application after launching it from a URL such as from a web browser from another application, you might have found it hard to debug what happens right after application launch because you weren't the one launching your application.

Well we have this same problem in iPhone OS 3.0 with push notifications when you're launching your applications from the View button and alert. The Xcode team has added a new feature to iPhone OS 3.0 to help you debug these situations and here to demonstrate this as well as to show you how to create a simple remote notification app, is my teammate Justin Santamaria. Thank you.

[ Applause ]

Thanks Chris. Hi, my name is Justin Santamaria and I'm an iPhone Applications Engineer for the iPhone team. I get the honor today of giving a demonstration about what Chris and Kris have been talking about for the past hour or so. So, when I found out I was going to do this demo I had to think about what kind of service I was going to do.

I think one of the great uses of the push notification service is going to be chat style applications or status update services and I was-- decided to write my own service but I kind of think that the general ones are kind of locked up. There are some big players already.

So I thought, you know, what do I like to do? Well, I like to complain and I like to complain a lot. And I was talking to my friends and it turns out that they like to complain too though they may not admit it. So what I did is I wrote an app called Squawker and I like to show you that now. So I'm going to go ahead and launch this app and give you a quick tour. So here we do, we have the main screen here and we have what you'd expect from status update applications.

We've got an icon, we've got a name, the latest status, and a date. No one is in a good mood today, it looks fine but that's the point. We can go ahead and select the name here. We're going to select Chris and we see a nice big icon for him, some bold text there with his latest status and the date and some history down there of things he's squawked about before. Was there potato salad at lunch here? All right, so very simple application.

It's only a couple of view controllers and I'd like to show you what's under the hood here. OK. So like I said, we have a couple of view controllers. We have the root view controller and the detail view controller that showed these two panels of the application. Now I'm not going to go into the view controllers right now. You can go ahead and check it-- and check the labs throughout the conference as that's a big part of the iPhone OS view controller structure. What I am going to do is go ahead and quickly peruse this account object.

Now this account object is a thing that connects to my Squawker server and it has username and password information. It also can get updates free for an account which means it gets the list of the people I'm listening to squawk and whatnot. So it's important to note that for the purpose of this demo, this is the code that your app currently has when communicating to your service. And now what I'd like to do is to take this app and enable push notifications for it.

[ Pause ]

So I'm going to go ahead and go to the application delegate here. In this case it's the Squawker App Delegate. Get a bigger view here. And we're going to notice there are a couple of methods. The one in particular that I'm interested in is application didFinishLoading. Right now, it's pretty basic stuff.

It simply sets up the window and whatnot and then instantiates my model object, the account, and goes ahead and updates the account. In order to enable push notifications here all the first thing I need to do is go ahead and register for remote notification types. Now in my particular app I thought about it and I definitely want to sound because I want you to be able to hear it if it's in your pocket or purse.

I did a badge because it'd be nice to have an unread count of squawks and you know what it's-- if I'm complaining I want to know-- I want you to know what I'm complaining about when I complain about it. So I went ahead and I put in an alert.

So it's going to show right up there whenever someone squawks in my list. Now as a result of this, I'm going to get one of two callbacks. The first one is the application didRegisterForRemoteNotificationsWithDeviceToken. And again the argument is in NSData structure. Now this is that opaque piece of data that you need to send to your server.

So the particular call here account send not-- remote notifications to device-- SendRemoteNotificationsDeviceToken is a piece of code that you're going to have to write that you put-- that it puts the device token up to your server. The second method is the failure case, application didFailToRegisterForRemoteNotificationsWithError. Now again, you're app should still function perfectly well if you're unable to register for remote notifications.

So all I've done here is go ahead and print a log so that I can go to the console and see what's wrong if I ever hit this. And just a reminder, you will hit this if you run it in the Simulator since push notifications aren't supported there.

Another application delegate callback that I might be interested in is the application didReceiveRemoteNotification. Now as Chris mentioned earlier if your applications running and we received a push notification for your application, the iPhone OS will not do anything with that but pass it directly to your application. That means no badge is going to be updated, no sounds going to be played and no alerts are going to be shown.

Instead, this message is going to get invoked on your application delegate. And in this case all I'm doing is telling my model object to go ahead and hit the server and update the account.

So, you need to think about what's appropriate for your application and go ahead and do that.

So we have the basic methods here that allow us to receive and respond to remote notifications as well as register, but I want to get slightly fancy here. I think it would be great that when I got a squawk from a given individual, if I could go straight to that person's detail view and I could see their large icon and their history.

So what I can do is instead of using application didFinishLaunching, I can substitute that with application didFinishLaunchingWithOptions. Now what this does is it provides an optional-- another dictionary called the Launch Options Dictionary and in there is a dictionary that represents the payload directly from the push notification server. Now with that, I can go down here and after I've done my usual registrations and whatnot.

Oops that-- it scrolled up a little. That's good. We can go ahead and grab that push dictionary out of the Launch Options Dictionary with the key UIApplication launch options remote notification key. Now when is this dictionary here? This dictionary is present whenever the user clicks on the action-- not clicks, taps on the Action button for a push notification alert.

It's not going to be there if there's a badge there, a sound played and the user tapped on the icon. It's only there from an alert. And what I've done here is I go ahead and set up my view, detailed view controller, set up its internal state and go ahead and put it on the view controller stack and again that's just view controller stuff that you can check out later. Finally, this particular method, a launch application with options, application didLaunchWithOptions returns the bullets as supposed to a void so I go ahead and return yes. So what I'm going to do now is save my project, build it, try to install it here.

OK, now I'm going to stop it because I actually want a push to come through when it's time. OK, so I'm going to wait for a squawk. [Squawk] Now that's a branded sound. Let me tell you. Well Chris, it's a little late to be regretting things and I'm sorry about that. But I'm going to go ahead and click Tab View here and I'm going to launch my application oh, but wait.

It didn't go to the detailed view controller. So, in the past it's been kind of tricky to debug because you weren't able to attach Xcode to a process that was launched externally. You might have run into this if you're using custom URLs in the past or if you just wanted the user to tap and then start debugging. But Xcode actually has a new feature that I'd like to show you now.

So I'm going to go back to the main screen of Xcode and I'm going to go these groups and files column and I'm going down to executables. And then I'm going to the executable and question, in my case it's Squawker. I'm going to hit command "I" which allows me to get info.

The third tab is the Debugging tab and there are two interesting options here. The first one is start executable after starting the debugger. Now this particular option is the behavior that you and I are both familiar with with Xcode today. This means that when you click on Debug in Xcode, Xcode will launch the application and immediately attach to the process.

This second thing is what we're interested in today. Wait for next launch/push notification. Now what this does when you tap debug on Xcode is Xcode does not launch the process. Instead Xcode waits for the next particular launch of that process and then attaches once it sees that it's been launched.

If you're familiar with DDB this is similar to wait for. So I'm going to go ahead and select that. I'm going to ahead and break where I think I might be having a problem, which is here. I'm going to switch to this bigger view for you. So I've broken here. I want to see what's in that dictionary. And I'm going to go ahead and click Debug.

And what's going to happen is instead of launching the application we get a dialog waiting for Squawker to launch. The debugger will attach to the process the next time it is launched. And so I'm going to go ahead and switch back to the phone and we're going to wait for a squawk.

[ Pause ]

[ Squawk ]

Now, I'm going to dignify that. So what I'm going to do here is I'm going to switch back to the demo machine. So you can see what happens with Xcode when I tap view. So I'm going to do that right now. The dialog disappears and sure enough we break right where we set that break point.

[ Applause ]

So I'm going to go ahead and bring up the Debugger Console here and I'm printing out that push dictionary. And sure enough we have APS here with the alert, the badge, and the sound and among the custom keys we have this key value pair squawker equals Chris.

But if we notice, the squawker in this case is lowercase but in my code I have an uppercase S that I'm looking for. So in this particular case the fix is trivial. I'm going to go ahead and make that lowercase. Demo bugs are always easier. Go ahead and build it.

[ Pause ]

I'm going to go ahead and cancel 'cause I'm feeling pretty good today and go back to the app and wait for last-- one last squawk. [Squawk] Well I'm finishing up, I promise and I'm going to go ahead and tap view here and voila, we went straight for the detail view controller. [Applause] Thank you.

[ Applause ]

So this particular feature of Xcode as well as push notification services-- the push notification service really enables a whole new type of application experience and I'm really excited to see what you guys come up with.

Thank you very much.

[ Applause ]

Thanks Justin. So if you need more information, please contact our Evangelist Matt Drance or check out the great documentation that we have on-line at developer.apple.com. We have a push notification service program and guide which is awesome as well as human interface guidelines that have been updated for iPhone OS 3.0 and the push service.