READ THIS FIRSTUpdate: 3-4-2016: If you're finding this blog and looking for information related to Azure Mobile Services, I'd strongly recommend checking out Azure Mobile Apps. Azure Mobile Apps is a new version (consider it a v2) of Azure's mobile backend support. All of the same features of Azure Mobile Services are there, with a lot of other very cool features to go along. You can read more about Azure Mobile Apps, and how to transition from Azure Mobile Services, here.
Welcome to Day 27 of the 31 Days of iOS. Yesterday, we started a two part series on Push Notifications. Yesterday was all about getting things set up. For push notifications getting set up is a particularly complex matter. Provided you had no issues with yesterday though, you should be ready to continue on and actually code and test your push notifications. One VERY IMPORTANT thing I’d like to point out is that you NEED to be a registered iOS developer in order to follow along today. There are steps you can’t take (like moving the app to a device) unless you are. Also, you can’t test push notifications on the simulator, you’ll need to have an iOS device in order to test this out. We won’t be doing any coding today as there is a lengthy set up process we need to go through first involving the Apple developer portal. Tomorrow we’ll implement all of the code and actually test out our push notifications. We’ll be starting with a brand new project, but if you’d like to follow along with the completed code, you can access it here.
A bit about client server stuff
In order to test and demonstrate push notifications, we have to have some way to send those push notifications. Unfortunately, there isn’t a way to do that from the Apple dev portal. What we really need is a computer that can send information to Apple’s Push Notification Service (APNS) in order to have it deliver the push notification. I could always run something locally or deploy something somewhere but in order to make things as easy on me as possible and not focus on the server side today, I’m going to use something I am familiar with, Windows Azure Mobile Services. This will allow me to easily test out sending a push notification without us getting into specifics of how it’s done. Once you’re done reading this, if you’re interested I have a bunch of other articles on what you can accomplish with Mobile Services besides just testing push which we’ll do today.
Creating our project
Open up Xcode and choose File, New, Project. We’ll use a Single View Application and name it DayTwentySix (I realize it’s DayTwentySeven but will explain the naming next):
Note the Bundle Identifier is set to the Company Identifier with the Product Name appended. This is the same Bundle Identifier that I entered during the last article when creating an App ID. These MUST match in order for our push notifications to work correctly. For today, we don’t need a very fancy UI, but we will need to display some info. Open up MainStoryboard.storyboard and drag a label onto your view. Once that is done, your UI will look like this:
Now, open the Assistant Editor from the top right of Xcode and control + click and drag from the label to your code behind to create a new outlet. Now your ViewController.h should look like this:
Now we can switch over to the AppDelegate.
Registering for push notifications
Open up AppDelegate.m and look at the application: didFinishLaunchingWithOptions method. As you’ll know from reading about the application life cycle, this method is called when your app starts and is a great place to do any global initialization. It’s also where we want to register our app for push notifications. We do this by using the application object sent into the method and calling it’s registerForRemoteNotifications method:
Notice here that I’ve registered for UIRemoteNotificationTypeBadge, UIRemoteNotificationTypeSound, and UIRemoteNotificationTypeAlert. These are all three of the notification types that I might use in my application. There is one other type, UIRemoteNotificationTypeNewsstandContentAvailability, that you might be interested in if making an app that resides in the newsstand (such as a magazine) but we’re going to skip it today. Your app may not want badge, sound, and alert type notifications so you’ll have to decide which types to request. As a general rule of thumb, only request permissions for things you know you’re going to use. After putting that code in and running our app, the first thing the user will see when their app runs will be a request for permission to send push notifications:
This brings up a very important caveat to push notifications: users DON’T have to allow push notifications for your app. That means that they can install your app and allow push notifications or not. You don’t really have any control over it. Make sure your app is designed in such a way that if push notifications aren’t working, or aren’t allowed, your app will still function. Now regardless of if the user taps Don’t Allow or OK they’ll continue on to your app. However, behind the scenes something is happening. First, the user’s choice is being saved in the Notification options under the Settings app (we’ll look more at this later). Second, if they did hit OK to allow push notifications, the device is communicating with the APNS servers to get a device token.
Getting the device token
The next method we need to handle is application: didRegisterForRemoteNotificationsWithDeviceToken. This method will automatically be called when the device hears back from APNS with a token. This token uniquely identifies the user’s device and your app running on their device. This is how it’s ensured that the token is sent to the right place. So let’s implement that method and just have it log the token:
When we run our app now, we print out a token that looks like this: <867ee0d4 9b979be4 bd5e7155 57900f38 6d2d366f 1ff9263f bb26cb76 4254f483>. To you and me that is a meaningless string of numbers and letters. However, APNS can use it to direct a message back to your device. The next step would be to do something with that token. Normally, this is where we would want to send our push notification to a server for saving so that the server could then use the token to send a message to our device. Since we’re less concerned with the server implementation today, we’re going to skip this part. Later on, once we’re finished with the app side, we will test a push by manually pulling the token that is getting logged out and using it.
Receiving a push
When our app receives a push notification, if the app is running in the background, the notification is displayed according to what type of notification it was (badge, sound, alert) and what the user has selected in their Notification settings (still to come). If the app is in the foreground though, the application: didReceiveRemoteNotification will be called. We’ll implement that method to just log the info sent over:
Now we need to do some app settings changes.
App settings changes
In Xcode, click on your project in the Project Navigator (top left of Xcode) to view the Project and Target settings. You’ll want to make sure you have the Target selected and then check that the Bundle Identifier matches what you set up earlier and what you used in the Apple dev portal:
Once that is done, switch to the Build Settings column (two down from Summary). Here, you want to look for the Code Signing section and change the Code Signing Identity:
Here I’ll select the drop down next to Code Signing Identity and choose the one I created yesterday: Day Twenty Six Push. If you have multiple profiles available, notice that you can only choose ones that are set up with the wildcard (such as the team provisioning profile) or ones that specifically match your app’s bundle identifier. Now we can test out sending a push notification.
What you’re not seeing (the server stuff)
As I mentioned at the top of this article, you really need to have some way to communicate with the APNS servers to tell them to send a push notification to a token in order to test out push notifications. There are many services out there that can handle push notifications for you in addition to code bases that you could use to deploy your own push server (just check GitHub). Today I’m going to use Windows Azure Mobile Services to do the actual push notification because it’s very simple to get set up and use. I don’t want to focus on how to do this today because that isn’t really the goal though. Essentially, what I’m skipping showing you is the following:
- Logging in (or signing up for free) to Windows Azure
- Creating a new Mobile Service
- Creating a new scheduled script
- Making the script send a push notification to my device using the token we pull from the logs
Those steps aren’t complicated but outside the scope and focus of this article.
Receiving the push in the app
If our app is running and we send the push notification, the application: didReceiveRemoteNotification method is called on the AppDelegate. Currently we’re just logging that message. So, if I send an alert over, this is what I’ll see in the logs:
It would be up to me to inspect the data that came over and figure out what I wanted to do from within my app. Let’s take a look and see what happens if our app isn’t in the foreground when we receive the push.
Receiving the push out of the app
There are a few different ways an Alert message might be received. If my settings for an alert is to show a banner, we’d see this:
If alerts are setup to show full alerts, we’d see this:
If the user were to tap Launch from this alert, a special option would be sent into the application: didFinishLaunchingWithOptions method if your app wasn’t currently running. If alerts aren’t set up to show as alerts or as banners, or even if they are, the alert will also show up in the Notification Center which you can access by dragging down from the top of the screen:
You can also (or just) send over a badge field with a number to put a numbered badge on top of your app icon:
This is very common with messaging apps as a way of indicating how many unread messages the user has. Other data fields you can send over include sound if you want to play a sound file, payload if you just want to send over some form of data, and expiry. The Way expiry works is that it specifies what date and time your message should no longer be delivered on. If the device is off or not receiving a signal, a push notification can’t be delivered at that time. APNS will continue to try though. However, some push notifications may be time sensitive and you may not want to deliver them past a certain time. For example, if I was building a deal-a-day app (like Groupon) and I was delivering an alert notification each day to tell you about that day’s deal, I probably wouldn’t want to tell you about yesterday’s deal if you just turned your phone on today. You can use expiry to make sure that doesn’t happen.
Updating the UI when a push is received
One important thing you’re probably going to want to do is know how to trigger different areas of your application when a push notification is received and the app is in the foreground. We’ll take a look at one way to do that right now. Our goal is to update the label on our view when a push is received. To do this, we’ll modify the application: didReceiveRemoteNotification method:
Here we’re getting a reference to the app’s window’s rootViewController and casting that to our ViewController class. We can then use that to directly update the label’s text. Now when we run our app and receive a push notification, the text will be updated:
If you launch the Settings application from the home screen and go to the Notifications area, you can edit how push notifications are handled for each application. You can choose whether or not to show things for the app in the Notification Center and if so, how many. You can change the Alert Style from banner, to normal alert, or nothing. You can also choose whether badges or sounds work as well as if alerts should be visible from the lock screen.
Remember that every user has access to this and can turn on and off push notifications for your app. Make sure your app is capable of handling things with no push notifications allowed.
Other important things
There are a few other server side considerations you should be aware of. First, when we set up our certificates and profiles yesterday, we did it for the developer version. You’ll need to go through the same steps again to create a production version of those things. Additionally, the p12 file you end up with is used to sign all of your requests for push notifications so whatever server is doing that for you (in my case, Windows Azure Mobile Services), will need to have that uploaded to it. Additionally, those certs you get for pushing expire after a year, so keep the date in mind so you can generate new certs before your old ones expire. Lastly, the tokens you get on your device and then send to the server can expire or be marked invalid by APNS. Fortunately, APNS will tell your server that they have expired so you can stop trying to send to them.
Today we went through all the code necessary for push notifications with APNS. Additionally, we looked at the different kinds of notifications you can receive on the client as well as how they can be turned on and off by users. We touched on the server side without getting our hands too dirty there. You should now have a good understanding of how push notifications work with iOS and how you can implement them yourself. You can download the completed code from today’s walkthrough here (remember it will be named Day Twenty Six).
- Apple (12) ,
- Azure (83) ,
- Mobile (100) ,
- Mobile Services (50) ,
- Objective-C (55) ,
- iOS (71) ,
- XCode (50)