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

Push Notifications on iOS for Programmable Chat


(error)

Danger

Programmable Chat has been deprecated and is no longer supported. Instead, we'll be focusing on the next generation of chat: Twilio Conversations. Find out more about the EOL process here(link takes you to an external page).

If you're starting a new project, please visit the Conversations Docs to begin. If you've already built on Programmable Chat, please visit our Migration Guide to learn about how to switch.

Push notifications are an important part of the mobile experience. Users have grown accustomed to having push notifications be a part of virtually every app that they use. The iOS Programmable Chat SDK is built to have push notifications integrated into it.


Enable push notifications for your Service instance

enable-push-notifications-for-your-service-instance page anchor

IMPORTANT: The default enabled flag for new Service instances for all Push Notifications is false. This means that Push will be disabled until you explicitly enable it. To do so, please follow our Push Notification Configuration Guide.

Note: You will need to configure the sound setting value for each push notification type you want the sound payload parameter to present for, with required value. More information can be found in the above mentioned Push Notification Configuration Guide.


Managing your push credentials

managing-your-push-credentials page anchor

Managing your push credentials will be necessary, as your device token is required for the Chat SDK to be able to send any notifications through APNS. Let's go through the process of managing your push credentials.

The AppDelegate class contains a series of application lifecycle methods. Many important events that occur like your app moving to the background or foreground have event listeners in this class.

When working with push notifications in your iOS application, it is quite likely you will find yourself needing to process push registrations or received events prior to the initialization of your Chat client. For this reason, we recommend you create a spot to store any registrations or push messages your application receives prior to the client being fully initialized. The best option here is to store these in a helper class to which your application delegate can obtain a reference. This way, your Chat client can process these values post-initialization if necessary or real-time otherwise. If you are doing a quick proof of concept, you could even define these on the application delegate itself but we recommend you refrain from doing this as storing state on the application delegate is not considered a best practice on iOS.

We will assume that you have defined the following properties in a way that makes them accessible to your application delegate method and Chat client initialization:

Chat Push State Variables

chat-push-state-variables page anchor
Objective-C
Swift

_10
@property (nonatomic, strong) NSData *updatedPushToken;
_10
@property (nonatomic, strong) NSDictionary *receivedNotification;
_10
@property (nonatomic, strong) TwilioChatClient *chatClient;

Your users can choose to authorize notifications or not - if they have authorized notifications, you can register the application for remote notifications from Twilio. Typically, you would do this in AppDelegate.swift in the didFinishLaunchingWithOptions function.

User Notification Settings

user-notification-settings page anchor
Objective-C
Swift

_24
// For iOS 10 and later add this to the didFinishLaunchingWithOptions function or a similar place
_24
// once you get granted permissions
_24
if (@available(iOS 10.0, *)) {
_24
UNUserNotificationCenter *currentNotificationCenter = [UNUserNotificationCenter currentNotificationCenter];
_24
[currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings) {
_24
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
_24
[UIApplication.sharedApplication registerForRemoteNotifications];
_24
}
_24
}];
_24
}
_24
_24
// For iOS versions before 10 you should add such implementation
_24
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
_24
if(notificationSettings.types == UIUserNotificationTypeNone) {
_24
NSLog(@"Failed to get token, error: Notifications are not allowed");
_24
if (self.chatClient) {
_24
[self.chatClient registerWithToken:nil];
_24
} else {
_24
self.updatedPushToken = nil;
_24
}
_24
} else {
_24
[UIApplication.sharedApplication registerForRemoteNotifications];
_24
}
_24
}

After successfully registering for remote notifications, the Apple Push Notification Service (APNS) will send back a unique device token that identifies this app installation on this device. The Twilio Chat Client will take that device token (as a Data object), and pass it to Twilio's servers to use to send push notifications to this device.

Objective-C
Swift

_17
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
_17
if (self.chatClient && self.chatClient.user) {
_17
[self.chatClient registerWithNotificationToken:deviceToken
_17
completion:^(TCHResult *result) {
_17
if (![result isSuccessful]) {
_17
// try registration again or verify token
_17
}
_17
}];
_17
} else {
_17
self.updatedPushToken = deviceToken;
_17
}
_17
}
_17
_17
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
_17
NSLog(@"Failed to get token, error: %@", error);
_17
self.updatedPushToken = nil;
_17
}

We print an error it it fails, but if it succeeds, we either update the Chat client directly or save the token for later use.


Provisioning Apple Developer credentials for APN Pushes

provisioning-apple-developer-credentials-for-apn-pushes page anchor

Make sure you have created a push certificate on the Apple Developer Portal for your application first - for testing purposes, this should be a Sandbox certificate, but you will need a Production certificate for applications uploaded to the App Store.

We're going to need to export both a certificate and a private key from Keychain Access:

  1. Start the "Keychain Access" application on your Mac
  2. Pick the "My Certificates" Category from the top menu
  3. Right-click the "Apple Development iOS Push Services" certificate for your application's bundle identifier
  4. In the popup menu choose "Export…"
  5. Save it as "cred.p12" without protecting it with password (leave the password blank)
  6. Extract the certificate from "cred.p12" into a "cert.pem" file - run the following command in terminal:

_10
openssl pkcs12 -in cred.p12 -nokeys -out cert.pem -nodes

  1. In the cert.pem file, strip anything outside of "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" boundaries, such as the "Bag Attributes"
  2. Extract your private key from the "cred.p12" (PKCS#12) into the "key.pem" (PKCS#1) file using the following command in terminal

_10
openssl pkcs12 -in cred.p12 -nocerts -out key.pem -nodes

The resulting file should contain "-----BEGIN RSA PRIVATE KEY-----". If the file contains "-----BEGIN PRIVATE KEY-----" and run the following command:


_10
openssl rsa -in key.pem -out key.pem

Strip anything outside of "-----BEGIN RSA PRIVATE KEY-----" and "-----END RSA PRIVATE KEY-----" boundaries and upload your credentials into the Twilio Platform through the Console.

To store your Credential, visit your Chat Push Credentials Console and click on the Create a Push Credential button. This console is located here:

Programmable Chat Push Credentials Console(link takes you to an external page)

The Credential SID for your new Credential is in the detail page labeled 'Credential SID.'

You should also ensure you add your credential SID to the Access Token Chat grant for iOS endpoints request tokens. Each of the Twilio Helper Libraries makes provisions to add the push_credential_sid. Please see the relevant documentation for your preferred Helper Library for details.


_10
var chatGrant = new ChatGrant({
_10
serviceSid: ChatServiceSid,
_10
pushCredentialSid: APNCredentialSid,
_10
});

Nice! That's all we need to make sure the client has access to your device token!


Integrating Push Notifications

integrating-push-notifications page anchor

You could keep your face buried in your phone all day waiting for your crush to send you a Chat message telling you that they're interested. Or you could turn on push notifications and go about your life, only getting notified once you receive their message. Sounds like a better option, right? Push notifications are supremely useful tools to keep users up to date with the status of their communication channels. Let's go through the process for integrating push notifications on iOS.

The AppDelegate class contains a series of application lifecycle methods. Many important events that occur like your app moving to the background or foreground have event listeners in this class. One of those is the applicationDidFinishLaunchingWithOptions method.

Objective-C
Swift

_10
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

In this method, we're going to want to integrate push notifications for our app

Objective-C
Swift

_16
if (@available(iOS 10.0, *)) {
_16
UNUserNotificationCenter *currentNotificationCenter = [UNUserNotificationCenter currentNotificationCenter];
_16
[currentCenter requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionAlert | UNAuthorizationOptionSound
_16
completionHandler:^(BOOL granted, NSError *error) {
_16
// Add here your handling of granted or not granted permissions
_16
}];
_16
currentNotificationCenter.delegate = self;
_16
} else {
_16
NSDictionary* localNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
_16
if (localNotification) {
_16
[self application:application didReceiveRemoteNotification:localNotification];
_16
}
_16
_16
[UIApplication.sharedApplication registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
_16
[UIApplication.sharedApplication registerForRemoteNotifications];
_16
}

The above code snippet asks the user's permission for notifications, and if granted, registers for remote (push) notifications. That's it! We're now registered for notifications.


Receiving notifications in our app lets us react to whatever event just occurred. It can trigger our app to update a view, change a status, or even send data to a server. Whenever the app receives a notification, the method didReceiveRemoteNotification is fired

Did Receive Notification

did-receive-notification page anchor
Objective-C
Swift

_34
// For iOS 10 and later; do not forget to set up a delegate for UNUserNotificationCenter
_34
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
_34
didReceiveNotificationResponse:(UNNotificationResponse *)response
_34
withCompletionHandler:(void (^)(void))completionHandler {
_34
NSDictionary *userInfo = response.notification.request.content.userInfo;
_34
// If your application supports multiple types of push notifications, you may wish to limit which ones you send to the TwilioChatClient here
_34
if (self.chatClient) {
_34
// If your reference to the Chat client exists and is initialized, send the notification to it
_34
[self.chantClient handleNotification:userInfo completion:^(TCHResult *result) {
_34
if (![result isSuccessful]) {
_34
// Handling of notification was not successful, retry?
_34
}
_34
}];
_34
} else {
_34
// Store the notification for later handling
_34
self.receivedNotification = userInfo;
_34
}
_34
}
_34
_34
// For iOS versions before 10
_34
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
_34
// If your application supports multiple types of push notifications, you may wish to limit which ones you send to the TwilioChatClient here
_34
if (self.chatClient && userInfo) {
_34
// If your reference to the Chat client exists and is initialized, send the notification to it
_34
[self.chatClient handleNotification:userInfo completion:^(TCHResult *result) {
_34
if (![result isSuccessful]) {
_34
// Handling of notification was not successful, retry?
_34
}
_34
}];
_34
} else {
_34
// Store the notification for later handling
_34
self.receivedNotification = userInfo;
_34
}
_34
}

We will pass the notification directly on to the Chat client if it is initialized or store the event for later processing if not.

The userInfo parameter contains the data that the notification passes in from APNS. We can update our Chat client by passing it into the singleton via the receivedNotification method. The manager wraps the Chat client methods that process the notifications appropriately.


Integration upon client startup

integration-upon-client-startup page anchor

Once your Chat client is up and available, you can provide the push token your application received:

Objective-C
Swift

_17
if (self.updatedPushToken) {
_17
[self.chatClient registerWithNotificatrionToken:self.updatedPushToken
_17
completion:^(TCHResult *result) {
_17
if (![result isSuccessful]) {
_17
// try registration again or verify token
_17
}
_17
}];
_17
}
_17
_17
if (self.receivedNotification) {
_17
[self.chatClient handleNotification:self.receivedNotification
_17
completion:^(TCHResult *result) {
_17
if (![result isSuccessful]) {
_17
// Handling of notification was not successful, retry?
_17
}
_17
}];
_17
}


To update badge count on an application icon, you should pass badge count from the Chat Client delegate to the application:

Objective-C
Swift

_10
- (void)chatClient:(TwilioChatClient *)client notificationUpdatedBadgeCount:(NSUInteger)badgeCount {
_10
[UIApplication.currentApplication setApplicationIconBadgeNumber:badgeCount];
_10
}

Next: Notifications on Android


Rate this page: