Apple Push Notifications (APNS)

Piyush Sharma
Jul 6, 2018 · Unlisted

iOS developers love to imagine users of their app using the app all day, every day. Unfortunately, the truth is that users have to close the app sometimes and perform other activities.

Happily, push notifications allow developers to reach users and perform small tasks even when users aren’t actively using an app.

Push notifications can:

  • Display a short text message
  • Play a notification sound
  • Show a badge number on the app’s icon
  • Provide actions the user can take without opening the app
  • Show a media attachment
  • Be silent, allowing the app to wake up in the background and perform a task

Before you get started, you will need the following to test push notifications:

  • An iOS device, Push notifications do not work in the simulator, so you’ll need an actual device.
  • An Apple Developer Program Membership. Since Xcode 7, you can test apps on your device without a program membership. However, to configure push notifications you need a push notification certificate for your App ID, which requires the program membership.

Getting Started

There are three main tasks that must be performed in order to send and receive a push notification:

  1. The app must be configured and registered with the Apple Push Notification Service (APNS) to receive push notifications.
  2. A server must send a push notification to APNS directed to one or more specific devices. Sending push notifications is a responsibility of the app’s server-component and is usually implemented differently from one app to the next.
  3. The app must receive the push notification, so that it can perform tasks or handle user actions using callbacks in the application delegate.

Step 1: The Certificate Signing Request

We are going to produce a Certificate Signing Request (CSR) file that we’ll use later on to create a SSL certificate for push notifications.

Follow these steps to create CSR (Code Signing Identity):

  1. On your Mac, go to the folder ‘Applications’ ► ‘Utilities’ and open ‘Keychain Access.’
  1. Go to ‘Keychain Access’ ► Certificate Assistant ► Request a Certificate from a Certificate Authority.

2. Fill out the information in the Certificate Information window as specified below and click “Continue”
• In the Email Address, put your email address to identify with this certificate
• In the Common Name field, enter your name
• In the Request group, select “Saved to disk” option

3. Save the file to your hard drive.

4. We will use this CSR (.certSigningRequest) file to create project/application certificates and profiles, in Apple developer account.

Step 2: Create an App ID

Let’s first understand what is the difference b/w an App Id and Bundle Id ?

A bundle ID precisely identifies a single app. A bundle ID is used during the development process to provision devices and by the operating system when the app is distributed to customers. No two applications can have the same bundle identifier.

During the development process, you use the bundle ID in many different places to identify the app.

Whereas, An App ID is a two-part string used to identify one or more apps from a single development team.

An App ID represents one or more applications in Apple’s system. It consists of two components, a Team ID and a bundle ID search string.

The Team ID is the component you don’t need to worry about is. It’s generated by Apple and prepended to the bundle ID search string.

There are two types of App IDs:

An explicit App ID, used for a single app, and wildcard App IDs, used for a set of apps, an explicit App ID doesn’t contain a wildcard.

A wildcard App ID is a bit different in that it can be used for one or more applications.

The above App ID can be used for several bundle identifiers.

Time to create App ID…

We will be creating a new App ID in the Apple Developer portal. This App ID is going to uniquely identify our app amongst others, and it will help APN servers to properly route the notifications. Actually, as you’ll see next, we’ll connect the App ID to a couple of other things: To a new certificate for push notifications, and to a provisioning profile that will let us run the app on a test device.

Create an app ID to identify your app in the Apple Developer portal. You need this ID when you create an SSL certificate for sending push notifications, when you create an iOS distribution certificate, and when you create a provisioning profile.

To assign an App ID to your app

  1. Sign in to your Apple Developer account at https://developer.apple.com/membercenter/index.action.
  2. Choose Certificates, Identifiers & Profiles.
  3. In the Identifiers section, choose App IDs. You’ll see a list with all the existing App ID values to the main window area. The new App ID that we’re about to create is going to be added to that list, but first, let’s click to the plus button existing in the top-right side

Let’s configure a new App ID . For starters, we need to fill in two fields:

6. Choose the default selection for an App ID Prefix.

7. Setting an Explicit App ID is necessary when you’re about to enable push notifications, as the App ID must match to specific app Bundle ID. For App ID Suffix, Just copy the value from your Xcode project, and paste it here.

8. Under App Services select Push Notifications.

9. Next, click to the Continue button, and wait for a confirmation page to show up. Verify that everything is okay, and then click to the Submit button to get finished. If you feel that something is wrong, then you can go back and change any of the previously set values.

Hopefully now you can see the new App ID being listed to the App IDs collection.

Step 3: Configure the App ID for Push Notifications

Now let’s select the newly created App ID in the list so it gets expanded. Right after all the displayed services there’s a button titled Edit. Click it to proceed.

In the next step scroll down until you see the Push Notifications section. You’ll find two buttons there which you can use to create SSL Certificates for both the Development and Production stage. As we’re interested in the Development mode only, click to the first button as shown below:

It’s about time now to make use of the Certificate Signing Request file we created through the Keychain Access app a couple of parts ago. So, let’s keep going with that process, and in the first step of the guide just click to the Continue button. Here you get just some instructions on how to generate the CSR, in case you haven’t done so already.

Next, click to the Choose File… button so you can search for the CSR file that you generated in the first step. If you hadn’t changed the default file name, then you’re looking for a file titled CertificateSigningRequest.certSigningRequest

Finally, click to the Generate blue button that you can see in the following screenshot.

Great, you just created a new certificate(ssl) that will enable you to send push notifications in development (sandbox) mode. Now, you must download it and add it to the keychain (the Keychain Access app on Mac), so proceed by clicking to the Download button.

The file you just downloaded is named aps_development.cer. Spot it in your Downloads folder and double click on it, so it’s added to the collection of certificates in the Keychain Access app.

An important notice: When the Keychain Access app opens by double clicking to the .cer file, make sure that the new certificate is added to the login keychain, and not to the System or any other keychain. If that happens, then just drag and drop the certificate to the login keychain. That’s important for what we’ll do right next.

Once you locate the new certificate in the Keychain, right click on it, and then click to the Export “…” option.

Make sure that the .p12 file format is selected before you click to the Save button.

The Certificate Signing Request (CSR) that you send to Apple contains your public key, some personal information about you and is signed using your private key. Apple then uses the public key in the CSR to verify that your CSR came from you before issuing your certificate.

The .cer certificate file may contain the public key of the APN server or your public key. The .p12 certificate contains both the public key and private key(yours).

We are going to need it, however, in case we want to test push notifications from our server, where we have to provide the .p12 file before even sending our first notification.

Step 4: Register Your Device

Supposing that you are going to add your device for first time here, what you have to initially do is to plug it to your Mac and then go to Xcode. Open the Window > Devices & Simulators.

You’ll notice that there is a field called Identifier, containing a long string with letters and digits as its value. Double click on that value, and then copy it.

Now go back to the Apple Developer website, and click to the All option under the Devices category. Any existing registered devices will be listed to the main window area.

In the new form that appears, first set a name for your device in the Name field (for example, My iPhone X, or My iPad). Then, paste the device identifier you copied before in the UDID field, and you’re done.

Step 5: Create a Provisioning Profile for Development

On the Apple Developer page, click to the Development link in the Provisioning Profiles category. Any existing profile will be shown to the main window side, and in a few minutes our new one will be added there as well.

Now it’s time to connect the profile we’re creating to the App ID matching to our app. Locate and select the proper App ID value in the dropdown control and then move on.

Next, you must include your iOS Development certificate to the provisioning profile (supposing that you have at least one).

Continue, and get ready to select the device or devices that the app is going to be run to. Make sure that you won’t forget to select any devices which you want to test push notifications to. Once again, click Continue when you’re ready.

Lastly, give a name to your provisioning profile so you can distinguish it amongst others. I named it “PNDemo Development Profile“, but feel free to give any other name you desire.

Click Generate and wait for the next screen. When the new profile gets ready, you’ll be able to download it as shown next:

Step 6: Configure the Project

We have two goals to achieve here:

  1. Initially, we must enable the Push Notifications capability in the project, so we can actually get notifications on any device.
  2. We’ll properly set the values for both code signing and provisioning profiles that must be used by the app.

So, bring the app in Xcode in front of you and select the project in the Project Navigator. Make sure that you are in the General tab. What you have to do is to go to the Teamdropdown control, and select the proper team that will be used for provisioning.

If you see no entries in the Team, then you must go to Xcode > Preferences… menu, in the Accounts tab and add a new Apple ID. Provide the Apple ID and password matching to your Developer account, and click to the Add button to get finished.

Next, click to the Capabilities tab and go to the Push Notifications section. All you have to do here is to just turn the switch on.

Now open the Build Settings tab, and locate the Code Signing section. Expand the Provisioning Profile entry, and in the row titled Debug click to the Automatic value so as to display a list with all the existing provisioning profiles in your Developer account. Select the one with the name matching to the profile you downloaded and installed in the previous step.

Right above the Provisioning Profile you will find the Code Signing Identity entry. Click to the arrow in the left side to expand it, if it’s not already expanded. Similarly to what we just did, click to the iOS Developer (or iPhone Developer) value in the Debug row, and select a proper identity as shown next:

Now click to the Target to the left side of the General tab, and select the Project:

Go to the Code Signing section, and follow the exact same steps as above. First select the correct provisioning profile for the Debug mode, and then the proper Code Signing Identity.

Step 7: Register for Push Notifications

There are two steps to register for push notifications. First, you must obtain the user’s permission to show any kind of notification, after which you can register for remote notifications. If all goes well, the system will then provide you with a device token, which you can think of as an “address” to this device.

Open AppDelegate.swift and add the following import to the top of the file:

Lastly, add a call to registerForPushNotifications() at the end of application(_:didFinishLaunchingWithOptions:):

You invoke requestAuthorization(options:completionHandler:) to (you guessed it) request authorization for push notifications. Here, you must specify the notification types your app will use. These types (represented by UNAuthorizationOptions) can be any combination of the following:

  • .badge allows the app to display a number on the corner of the app’s icon.
  • .sound allows the app to play a sound.
  • .alert allows the app to display text.
  • .carPlay allows the app to display notifications in a CarPlay environment.

Update requestAuthorization to call getNotificationSettings() within the completion closure like this:

Step 1 is now complete, and you’re now ready to actually register for remote notifications. Update getNotificationSettings() with the following:

Here you verify the authorizationStatus is .authorized, meaning the user has granted notification permissions, and if so, you call UIApplication.shared.registerForRemoteNotifications().

Add the following two methods to then end of AppDelegate; these will be called to inform you about the result of registerForRemoteNotifications:

What Happens When You Receive a Push Notification?

When your app receives a push notification, a method in UIApplicationDelegate is called.

The notification needs to be handled differently depending on what state your app is in when it’s received:

  • If your app wasn’t running and the user launches it by tapping the push notification, the push notification is passed to your app in the launchOptions of application(_:didFinishLaunchingWithOptions:).
  • If your app was running either in the foreground, or the background, application(_:didReceiveRemoteNotification:fetchCompletionHandler:) will be called. If the user opens the app by tapping the push notification, this method may be called again, so you can update the UI, and display relevant information.

In the first case:

This code does three things:

  1. It checks whether the value for UIApplicationLaunchOptionsKey.remoteNotification exists in launchOptions. If it does, this will be the push notification payload you sent.
  2. If it exists, you grab the aps dictionary and pass it to createNewNewsItem(_:), which is a helper method provided to create a NewsItem from the dictionary and refresh the news table.
  3. Lastly, it changes the selected tab of the tab controller to 1, the news section.

To test this, you need to edit the scheme of App:

This option will make the debugger wait for the app to be launched for the first time after installing to attach to it.

Silent Push Notifications

If your app’s server-based content changes infrequently, or at irregular intervals, you can use silent notifications to notify your app when new content is available. A silent notification is a remote notification that doesn’t display an alert, play a sound, or badge your app’s icon. It wakes your app in the background and gives it time to initiate downloads from your server and update its content.

Create a Silent Notification: To send a silent notification, create a remote notification whose aps dictionary includes the content-available key.

Also, please note: If you are sending silent remote notification via Firebase Cloud Messaging(FCM), then you should use “content_available” : true. But if you are sending silent remote notification via Apple Push Notification service, then you should use the “content–available” : 1

When an iOS device receives a silent notification, the system wakes your app in the background and calls the application(_:didReceiveRemoteNotification:fetchCompletionHandler:) method of its app delegate. Your app has 30 seconds of wall-clock time to perform any tasks and call the provided completion handler.

Enable the Remote Notifications

To get started, go to App Settings -> Capabilities and turn on Background Modes for App. Check the last option, Remote Notifications:

Now your app will wake up in the background when it receives any push notification.

Common Issues

There are a couple problems that might arise:

Some notifications received but not all: If you’re sending multiple push notifications simultaneously and only a few are received, fear not! That is intended behavior. APNS maintains a QoS (Quality of Service) queue for each device with a push app. The size of this queue is 1, so if you send multiple notifications, the last notification is overridden.

Problem connecting to Push Notification Service: One possibility could be that there is a firewall blocking the ports used by APNS. Make sure you unblock these ports. Another possibility might be that the private key and CSR file are wrong. Remember that each App ID has a unique CSR and private key combination.

If you stop receiving push notifications, it is likely that your device token has changed. This can happen if you uninstall and reinstall the app. Double check the device token to make sure.

Few of the other APNS issues:

Possible Cause: Using an iOS certificate for the wrong environment

Description: Apple issues different SSL certificates for Development and Production purposes. You need to observe which one you use at any time or your devices will not be able to receive push notifications.

Recommended solution: Ensure that the type of the certificate that is selected as Active in Developer Platform matches the type of the iOS Provisioning Profile and the type of the iOS certificate that you use to sign the app.

For example, if you have signed your app using an iOS App Development certificate on a Development Provisioning Profile you need to upload and activate an “Apple Push Notification service SSL” Development iOS certificate in Developer Platform. Both certificates must be issued for the same App ID.

Possible cause: Using a wrong ios certificate

Recommended solution: Ensure that the active certificate in Developer Platform is “Apple Push Notification service SSL” (for example Apple Production iOS Push Services - com.example.sampleapp.p12), which is a server certificate, and not a client certificate that is used to sign apps.

Possible cause: Expired iOS certificate

Description: An iOS certificate cannot be used for sending push notifications after its expiration date has passed. iOS certificates can also be inactive because they were revoked or invalidated.

Recommended solution: Sign in to Apple’s Developer Center and ensure that your provisioning or development profile is active and that the respective certificates have not been expired, revoked, or invalidated.

APNS Flow Example:

Thanks for reading :)

Unlisted

Piyush Sharma

Written by

iOS Engineer

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade