Send Push Notifications to your iOS app
A basic understanding of Swift and Node.js is needed to follow this tutorial.
Pusher’s Beams SDKs and API make it easy to send push notifications to all of your iOS, Android and web users with one request.
For iOS, the service manages your app credentials and the lifecycle of device tokens which are both required for every request to the Apple Push Notification service (APNs).
You can subscribe your app user’s registered device to Interests, which act like persistent Pub/Sub topics, so that you can update many devices with the same request. Create as many interests as you need, and send unlimited push notifications.
In this tutorial, we will show you how to successfully configure APNs, integrate Beams iOS SDK into your project, and send one push notification to your iPhone using one of our server side SDK’s.
Step 1 - Sign up for a Pusher account
Before we can start building you will have to sign up for a Pusher account (or log in with your existing Pusher credentials).
Step 2 - Set up your free Beams instance
Head on over to the Products Dashboard and create your first Beams instance. With a free plan, you can send unlimited push notifications to up to 1000 devices during a billing month.
This will take you to our Quickstart wizard:
Select iOS and follow the instructions. The Quickstart will guide you through the following steps:
Configuring APNs
The first step of the Quickstart involves configuring your credentials with APNs.
All push notifications requests for iOS devices go through Apple Push Notification service (APNs), Apple’s service which delivers them to the device.
In order for Pusher to send them we need to generate APNs Key.
- Log into your Apple Developer Portal.
- Navigate to the keys section in the Apple Developer Portal where you can create the key. Enter the key name by your choice and be sure to check APNs checkbox. Proceed if you’re happy with the configuration and download and save the key on your computer. In the next step we will upload the key into our dashboard and configure your iOS integration.
If you’re lost check our documentation about APNs configuration here.
Uploading your APNs Key and Team ID
After you have configured your APNs Key, the next step is to upload your APNs Key through the Quickstart wizard:
We also need your team id which you can find here.
Step 3 - Integrating the Beams SDK into your iOS project
Now you will integrate the Beams SDK into your iOS project. This will send the deviceToken
to Pusher’s Beams service, which manages its lifecycle if it changes or if the user uninstalls the app.
Our SDK is available both on CocoaPods and Carthage so pick the one that you’re most familiar with.
To integrate Beams into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'PushNotifications'
Run the following command:
pod install
If you’re using Carthage specify the following in your Cartfile
:
github "pusher/push-notifications-swift"
Run carthage update
to build the framework and drag the built PushNotifications.framework
into your Xcode project
Before we start using our shiny SDK we need to create an instance of Beams SDK.
First, you enable push notifications in the Xcode project. Select your project in the project navigator and click on the Capabilities tab. Enable push notifications by turning the switch ON.
Import the SDK in your AppDelegate file with:
import PushNotifications
Create an instance:
let pushNotifications = PushNotifications.shared
For your iOS app to receive push notifications, it must first register the deviceToken
with APNs. You should do this when the application finishes launching, i.e. in its application:didFinishLaunchingWithOptions:
handler:
self.pushNotifications.start(instanceId: "YOUR_INSTANCE_ID")
self.pushNotifications.registerForRemoteNotifications()
APNs will respond with a device token identifying your app instance. This device token is passed to your application with the application:didRegisterForRemoteNotificationsWithDeviceToken:
method.
Pusher requires the deviceToken
in order to send push notifications to the app instance. Your app should register with Beams, passing along its device token. Add a handler for it:
self.pushNotifications.registerDeviceToken(deviceToken)
For more information check our SDK guide in the docs.
Finally, subscribe your device to an interest hello
:
self.pushNotifications.registerDeviceToken(deviceToken) {
try? self.pushNotifications.addDeviceInterest(interest: "hello")
}
When your server publishes a push notification to the interest hello, it will get passed to your app. This happens as a call to application:didReceiveRemoteNotification:fetchCompletionHandler:
in your AppDelegate
:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print(userInfo)
}
If you want to learn more about how interests work please read this guide.
Step 4 - Start sending push notifications
Push notifications are triggered by your servers to your Beams service. After a device using your iOS application subscribes to an interest on our service, your server can then send a push notification to that device by publishing to that interest.
Let’s start by creating a file called publish-body.json
with the request body for the publish:
{
"interests": [
"hello"
],
"apns": {
"aps": {
"alert": {
"title": "Hello",
"body": "Hello, world!🎉"
}
}
}
}
Before you run the curl
command, you need to get the instance id and its secret. You can get this information in the Pusher Dashboard “Keys” tab for your Beams instance.
Now send a push notification to your phone by executing this command:
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer $SECRET_KEY" \
-X POST "https://$INSTANCE_ID.pushnotifications.pusher.com/publish_api/v1/instances/$INSTANCE_ID/publishes" \
-d @publish-body.json
Note: Because push notifications don’t work in simulator, make sure that you’re running your application on a device (iPhone, iPad). We also recommend that you minimise your app by pressing the home button so that you see the push notification when it arrives.
You can send push notifications from your server by using one of our server SDKs. We currently support many languages from PHP, Python, Node.js to Java. Feel free to contact us on Twitter if we’re missing your language or with any other feedback about Pusher’s Beams SDKs and API.
Bonus 🎁 - sending push notifications with rich media
You can send rich media in a push notification to iOS devices, including images, GIFs, audio, and video clips. Including media in your push notification can increase the open rate and drive more engagement to your app.
Step 1 - Start by creating a Notification Service Extension
Choose File > New > Target and select Notification Service Extension.
A Notification Service Extension essentially intercepts certain remote notifications and allows you to handle the contents of the payload, including downloading and displaying remote media attachments, before displaying the notification to the user.
Once you’ve added the target, open it up, and you’ll see a couple of delegate methods – one for receiving a notification request and one for handling the expiration of the service extension. We’ll be focusing on the first one, didReceive(_:withContentHandler:).
The code in this method should look like this:
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
// Get the custom data from the notification payload
if let notificationData = request.content.userInfo["data"] as? [String: String] {
// Grab the attachment
if let urlString = notificationData["attachment-url"], let fileUrl = URL(string: urlString) {
// Download the attachment
URLSession.shared.downloadTask(with: fileUrl) { (location, response, error) in
if let location = location {
// Move temporary file to remove .tmp extension
let tmpDirectory = NSTemporaryDirectory()
let tmpFile = "file://".appending(tmpDirectory).appending(fileUrl.lastPathComponent)
let tmpUrl = URL(string: tmpFile)!
try! FileManager.default.moveItem(at: location, to: tmpUrl)
// Add the attachment to the notification content
if let attachment = try? UNNotificationAttachment(identifier: "", url: tmpUrl) {
self.bestAttemptContent?.attachments = [attachment]
}
}
// Serve the notification content
self.contentHandler!(self.bestAttemptContent!)
}.resume()
}
}
It may seem like a lot is happening here, but it’s straightforward really. Initially, we are exploring the notification’s payload for the dictionary named data
that contains the key attachment-url
. If this key exists, we download the media at the URL specified in the key’s value. See, easy!
The URLSession
downloads the media to temporary storage and appends a .tmp
file extension, which we need to remove so that the application can infer the file type and display it. So, to do this we need to move the file to the application’s local File Manager and that’s it – our media is ready to be attached to the notification content, and served to the user.
This is all the code needed in your Xcode project to display rich notifications in your application.
Step 2 - Trigger your request from the server
Now, you just need to make a few adjustments to the server that triggers push notifications to your application using our API.
Earlier, we mentioned that only certain notifications were intercepted by the Service Extension. So, how does iOS know which notifications to intercept? Well, you just add a mutable-content
tag to your payload and set it to 1
.
The final thing you need to do is to add the media attachment URL to the payload in its own dictionary that we’ve named ‘data’, but you can name it anything. Simply add a key-value pair to the dictionary, and as long as the key you’ve used in your Service Extension is the same as the key here, you’re done!
The following example is using a Node.js:
pusher.notify(['hello'], {
apns: {
aps: {
alert: {
title: "Pusher's Native Push Notifications API",
subtitle: "Bringing you iOS 10 support!",
body: "Now add more content to your Push Notifications!"
},
"mutable-content": 1,
category: "pusher"
},
data: {
"attachment-url": "https://pusher.com/static_logos/320x320.png"
}
}
});
That’s it! You can now send images, videos, audio, and GIFs!
You can change the URL to point to another media file, and see the results for yourself.
18 January 2018
by Luka Bratos