Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Registering for Notifications on iOS


Ready to send your first notification? Of course, you're not! That's why you're here. But don't worry, we'll get you registered so you can start sending notifications faster than a collision-free hash table lookup (OK, maybe not that fast).

A Notifications application involves two components:

  • A client (iOS) app that registers for and receives notifications
  • A server app that creates bindings and sends notifications

The aim of this guide is to show you how these two components work together when you register for notifications. Let's get to it!


Table of Contents

table-of-contents page anchor

Client: Registering a Device with APNS

client-registering-a-device-with-apns page anchor

Before working with Twilio Notifications, we'll need to register our device with APNS. This registration will happen every app launch, and in our AppDelegate and we can specify the type of notification (sound, alert, or badge) that we'd like to accept. On the first launch, iOS will prompt us to enable push notifications with a popup alert.

Register a Device

register-a-device page anchor
Objective-C
Swift

_15
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_15
// Override point for customization after application launch.
_15
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
_15
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings
_15
settingsForTypes:(UIUserNotificationTypeSound |
_15
UIUserNotificationTypeAlert |
_15
UIUserNotificationTypeBadge)
_15
categories:nil]];
_15
_15
[UIApplication sharedApplication] registerForRemoteNotifications];
_15
} else {
_15
[[UIApplication sharedApplication] registerForRemoteNotifications];
_15
}
_15
return YES;
_15
}

Once we've enabled notifications, iOS will send an asynchronous response to the app via the didRegisterForRemoteNotifications function. Make sure you've properly configured your iOS app for notifications or else the registration won't work.


Client + Server: Creating a Binding

client--server-creating-a-binding page anchor

Client

client page anchor

Once we've received a successful registration response from the didRegisterForRemote NotificationsWithDeviceToken method, it's time to create a Binding. A "Binding" represents a unique device that can receive a notification. It associates a unique device token (provided by iOS) with an identity and an optional set of tags that you define for your application. When you want to send a notification, Twilio will send your notification only to Bindings that match the parameters you specify (more on that later).

(warning)

Warning

In iOS 13, the format of the string returned when you call the description method on an NSData object has changed from previous iOS versions. This means that code that parses the device token string from a call like [deviceToken description] or similar, where deviceToken is an NSData object, will break in iOS 13.

The preferred way of creating a string of hex characters from bytes would be to iterate through each of the bytes and create a new string using a format string. There is an example in the Objective-C snippet for Creating a Binding.

The client app should send a request to the server containing the device token and any additional information the server might need to create the binding (typically Identity and BindingType). We'll use the NSURLSession networking API that is part of the iOS standard library to make the request. You could also use another library, such as AFNetworking(link takes you to an external page) or Alamofire(link takes you to an external page).

The last step on the client side is storing the Endpoint identifier generated by Twilio and included in the response. Storing the Endpoint and reusing it in subsequent requests will allow us to avoid creating duplicated Bindings when the device token changes. Here we use the KeychainAccess helper class from our quickstart app but you can use your own way of accessing the keychain.

Create a Binding (Client-side)

create-a-binding-client-side page anchor
Objective-C
Swift

_58
_58
- (NSString*) createDeviceTokenString:(NSData*) deviceToken {
_58
const unsigned char *tokenChars = deviceToken.bytes;
_58
_58
NSMutableString *tokenString = [NSMutableString string];
_58
for (int i=0; i < deviceToken.length; i++) {
_58
NSString *hex = [NSString stringWithFormat:@"%02x", tokenChars[i]];
_58
[tokenString appendString:hex];
_58
}
_58
return tokenString;
_58
}
_58
_58
-(void) registerDevice:(NSData *) deviceToken identity:(NSString *) identity {
_58
// Create a POST request to the /register endpoint with device variables to register for Twilio Notifications
_58
_58
NSString *deviceTokenString = [self createDeviceTokenString:deviceToken];
_58
_58
_58
NSURLSession *session = [NSURLSession sharedSession];
_58
_58
NSURL *url = [NSURL URLWithString:serverURL];
_58
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
_58
request.HTTPMethod = @"POST";
_58
_58
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
_58
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
_58
_58
NSDictionary *params = @{@"identity": identity,
_58
@"BindingType": @"apn",
_58
@"Address": deviceTokenString};
_58
_58
NSError* err=nil
_58
NSString *endpoint = [KeychainAccess readEndpoint:identity error:err];
_58
if (err == nil){
_58
[params setObject:endpoint forKey:@"endpoint"];
_58
}
_58
_58
NSError *error;
_58
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
_58
request.HTTPBody = jsonData;
_58
_58
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
_58
_58
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
_58
NSLog(@"Response: %@", responseString);
_58
_58
if (error == nil) {
_58
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
_58
NSLog(@"JSON: %@", response);
_58
_58
[KeychainAccess saveEndpoint:identity endpoint:response["endpoint"]]
_58
_58
} else {
_58
NSLog(@"Error: %@", error);
_58
}
_58
}];
_58
[task resume];
_58
}

In our server app, we'll receive the POST request. It'll contain the following four parameters.

namedescription
IdentityThe Identity to which this Binding belongs. Identity is defined by your application and can have multiple endpoints.
BindingTypeThe type of the Binding determining the transport technology to use. We will use apn here.
AddressThe device token obtained from iOS.
EndpointThe identifier of the device to which this registration belongs. This is generated the first time you create a Binding. Then you need to store it in the keychain and provide it in your subsequent registrations to avoid duplicating Bindings even if the device token changes.
(warning)

Warning

Do not use Personally Identifiable Information for Identity

Notify uses Identity as a unique identifier of a user. You should not use directly identifying information (aka personally identifiable information or PII) like a person's name, home address, email or phone number, etc., as Identity because the systems that will process this attribute assume it is not directly identifying information.

We'll use index.js in our server app and these four parameters to send an API call to Twilio, using the next generation Twilio Node Helper Library(link takes you to an external page). This will help us create a new Binding. We implement this logic in the /register endpoint, but this is not required. You can come up with your own API, and perhaps integrate it into a login or a session initialization flow.

Create a Binding (Server-side)

create-a-binding-server-side page anchor
Node.js
Python
C#
Java
Go
PHP
Ruby
twilio-cli
curl

_17
// Download the helper library from https://www.twilio.com/docs/node/install
_17
// Find your Account SID and Auth Token at twilio.com/console
_17
// and set the environment variables. See http://twil.io/secure
_17
const accountSid = process.env.TWILIO_ACCOUNT_SID;
_17
const authToken = process.env.TWILIO_AUTH_TOKEN;
_17
const client = require('twilio')(accountSid, authToken);
_17
_17
client.notify.v1.services('ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
_17
.bindings
_17
.create({
_17
endpoint: 'endpoint_id',
_17
tag: ['preferred device'],
_17
identity: '00000001',
_17
bindingType: 'apn',
_17
address: 'apn_device_token'
_17
})
_17
.then(binding => console.log(binding.sid));

Output

_20
{
_20
"account_sid": "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_20
"address": "apn_device_token",
_20
"binding_type": "apn",
_20
"credential_sid": null,
_20
"date_created": "2015-07-30T20:00:00Z",
_20
"date_updated": "2015-07-30T20:00:00Z",
_20
"endpoint": "endpoint_id",
_20
"identity": "00000001",
_20
"notification_protocol_version": "3",
_20
"service_sid": "ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_20
"sid": "BSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
_20
"tags": [
_20
"26607274"
_20
],
_20
"links": {
_20
"user": "https://notify.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Users/24987039"
_20
},
_20
"url": "https://notify.twilio.com/v1/Services/ISXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Bindings/BSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
_20
}

Now that we've registered the client app with APNS and created a Binding, it's time to send some notifications! Check out our Sending Notifications guide for more information.

Next: Sending Notifications »


Rate this page: