As of October 24, 2022, the Twilio Notify API is no longer for sale. Please refer to our Help Center Article for more information.
Notify makes it easy to send cross-platform notifications to your users. From in-app push notifications on Android and iOS to SMS fallbacks, Notify takes care of the heavy lifting.
Let’s build an iOS app that can receive and react to push notifications sent by the Apple Push Notification Service (APNS) and Twilio Notify.
Tools and Agenda
There are a few things you will need in order to run all of the code in this tutorial:
- An Apple Developer account
- Xcode version 7.3
- Node.js installed
- A free Twilio account
- Access to Notify – Request early access here
- An iOS device – push notifications don’t work in the simulator
To send push notifications we will need to:
- Create a Twilio Credential and a provisioning profile for your Apple developer account
- Configure a Node.js server to authenticate our iOS app
- Create a Binding for Twilio to send notifications to your device
- Write code to register your device with APNS
- Write code to receive notifications from APNS
- Bask in the glory of having a working app that you can modify to fit your needs
Configuring the server
We will build off the iOS Quickstart for Twilio Notify which uses Node.js on the server side to authenticate the iOS app.
Begin by cloning this repository for the Node server in your terminal:
git clone git@github.com:TwilioDevEd/notifications-quickstart-node.git
To send notifications on iOS, make sure you have your Apple push credentials configured with Twilio Notifications.
Follow this guide and make sure you have your certificate key and private key ready. Afterwards you should have a Twilio Credential of type APN with your certificate and private key as seen in this screenshot.
Make sure “Use this credential for sending to a sandbox APN” is checked.
We need a Twilio Service Instance SID to configure our Node server. Head to Services, click Create Service and under APN Credential SID, choose the push credential you just created and hit Save.
Next, grab your Account SID
and Auth Token
from your Twilio Console.
Open config.json
and replace following variables with these values you just gathered:
- TWILIO_ACCOUNT_SID
- TWILIO_AUTH_TOKEN
- TWILIO_CREDENTIAL_SID – This can be left blank, but is in the config file.
- TWILIO_NOTIFICATION_SERVICE_SID
Now run the Node server by entering the following in your terminal in the Node quickstart directory:
npm start
Setting up the iOS app
We can now move on to setting up our iOS app. I have a barebones project already written that you can use to get started with a full storyboard.
Start by cloning this repository:
git clone git@github.com:sagnew/NotifyQuickstart.git
Next open the Xcode project:
open NotifySwiftQuickstart.xcodeproj
In order for push notifications to work, you’ll have to make sure the bundle identifier in Xcode matches the provisioning profile you made in your Apple developer account. I used the name NotifyQuickstart
for mine, but you can use anything you want.
Creating a Device Binding
We need to have a function that makes requests to the Node.js server in order to register the device. A “Binding” represents a unique device that can receive a notification.
In ViewController.swift
replace the empty registerDevice(identity: String, deviceToken: String)
function with the following:
func registerDevice(identity: String, deviceToken: String) {
// Create a POST request to the /register endpoint with device variables to register for Twilio Notifications
let session = NSURLSession.sharedSession()
let url = NSURL(string: serverURL)
let request = NSMutableURLRequest(URL: url!, cachePolicy: .UseProtocolCachePolicy, timeoutInterval: 30.0)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let params = ["identity": identity,
"endpoint" : identity+deviceToken,
"BindingType" : "apn",
"Address" : deviceToken]
let jsonData = try! NSJSONSerialization.dataWithJSONObject(params, options: [])
request.HTTPBody = jsonData
let requestBody = NSString(data: jsonData, encoding: NSUTF8StringEncoding)
print("Request Body: \(requestBody)")
let task = session.dataTaskWithRequest(request) { (responseData:NSData?, response:NSURLResponse?, error:NSError?) in
if let responseData = responseData {
let responseString = NSString(data: responseData, encoding: NSUTF8StringEncoding)
print("Response Body: \(responseString)")
do {
let responseObject = try NSJSONSerialization.JSONObjectWithData(responseData, options: [])
print("JSON: \(responseObject)")
} catch let error {
print("Error: \(error)")
}
}
}
task.resume()
}
In this code we created an NSURLSession that will send an HTTP request to our Node server in order to register the device.
Now we need to call this function whenever the register button is tapped. Modify didTapRegister(sender: UIButton)
to contain the following code:
@IBAction func didTapRegister(sender: UIButton) {
if (TARGET_OS_SIMULATOR == 1) {
displayError("Unfortunately, push notifications don't work on the Simulator")
} else {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let deviceToken : String! = appDelegate.devToken
let identity : String! = self.identityField.text
registerDevice(identity, deviceToken: deviceToken)
resignFirstResponder()
}
}
Now when the button is tapped, the device will be registered and Twilio will be able to send notifications to it.
Before running the app, we’ll need some code to register the device with APNS and to receive the notifications.
Registering a Device with APNS
The code for receiving notifications on the iOS app lives in your AppDelegate.swift
.
We need to register the device with APNS, which will happen every time the app launches.
Open AppDelegate.swift
and replace the empty application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?)
function with the following:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let settings = UIUserNotificationSettings(forTypes: .Alert, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
return true
}
This will cause iOS to prompt you to enable push notifications with a popup alert on the first launch.
If you want access to the notification, it will arrive in JSON format and contains the message body as a String that in the didReceiveRemoteNotification
function.
In AppDelegate.swift
again, replace ‘application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])’ with the following code to finish things off:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
let message = userInfo["aps"]?["alert"] as? String
let alertController = UIAlertController(title: "Notification", message: message, preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(defaultAction)
self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
}
With this function we are ready to run the app and start receiving notifications.
Running the app and receiving a notification
Push notifications don’t work in the simulator so we need to run the app on a real device. This means that the Node server will be inaccessible to our iOS app as it is currently running on localhost.
We will use ngrok to make the Node server available outside of our development environment so that the mobile app can see it.
After installing ngrok, in a new terminal window run the following command and take a note of the forwarding URL generated.
$ ngrok http 3000
Now open ViewController.swift
and for the serverURL
variable, replace the placeholder value with your ngrok URL. Make sure to keep “/register” at the end of the URL as that will be the route on the Node server that our iOS app will send requests to.
Run the app on your device and you will get a prompt that asks if you want to receive notifications. Make sure you allow push notifications when this comes up. If you miss this prompt you can head to your settings, select “Notifications” and find the NotifySwiftQuickstart
app to allow notifications.
You should see a simple UI where you can enter an identity for the user. When you click the button, you will create a Binding which uniquely identifies a user on a certain device, running your application.
Navigate back to the node quickstart in your terminal so we can send a notification to the app. The code for this app lives in the notify.js
file. To send a notification to your iOS mobile app run this file, using the identifier you entered in the node app:
$ node notify.js YOUR_IDENTITY
You can see it in action here. I even locked my phone before sending the notification.
Notifications at your fingertips
Push notifications are useful in anything from games to social media to alert users when new information is available and you are now equipped to send them with Twilio Notify in your iOS applications.
Let’s take a moment to celebrate:
If you’re more of an Android fan you can check out this post my buddy Marcos wrote on push notifications for Android.
I can’t wait to see what you build, so contact me via the following channels and let me know how you’re using Twilio Notify:
- Email: sagnew@twilio.com
- Twitter: @Sagnewshreds
- Github: Sagnew
- Twitch (streaming live code): Sagnewshreds