iOS

iOS Mobile Push Gateway for APNs Tutorial for Real-Time Apps | PubNub

This page provides a walk-through demonstrating the start to finish process of building a working application utilizing PubNub Mobile Push Gateway for APNs. This all-inclusive tutorial includes:

  • Overview & Architecture

  • Preparing your Apple Development Environment.

  • Preparing your PubNub environment.

  • Building A Working Application.

  • Test Your Application

Tutorial Contents:

Overview & Architecture

PubNub’s Mobile Push Gateway for APNs makes delivering real-time push notifications to Android and iOS devices and removes the complexity of cross-platform message delivery to heterogeneous mobile applications by providing a easy to use publish API and a highly scalable, globally distributed, real-time network. PubNub Mobile Push Gateway for APNs can instantly deliver push notifications in parallel to both iOS and Android by acting as the provider between subscriber devices of all kinds and 3rd party services. PubNub’s Mobile Push Gateway for APNs eliminates the burden of developing an additional server side components for Apple Push Notifications and Google Cloud Messaging.

Apple Push Notification service

One traditional limitation of Apple’s Push Notifications is that they can only be received on supported iOS devices (iPad, iPhone, etc). However, the PubNub Mobile Push Gateway for APNs provides the ability to send messages to the APNs service from any client (iOS, Android, Java, Ruby, Python, etc) using the native PubNub sendMessage mechanism. This allows messages published to PubNub Mobile Push Gateway for APNs to be received as push notifications on any iOS device.

Architecture Components
  • PubNub Mobile Gateway for APNs

  • Apple Push Notification service

  • Your PubNub enabled Real-Time application

Push Certificate

The Apple Push Notification service requires that a Push Certificate be generated that uniquely identifies your PubNub enabled application to the APN service. This Push Certificate is uploaded to PubNub in the PubNub Admin Portal and is used to form a secure connection from PubNub Mobile Push Gateway for APNs to the APN service.

Device Token

Similarly, a Device Token is created for each client iOS device that registers with Apple to receive push notifications. The Device Token is analogous to a phone number; it contains information that enables APNs to locate the device on which the client application is installed. Normally, messages published to PubNub Real-Time Network are only accessible by native PubNub subscribers. When messages are published to a PubNub channel associated with an APNs Device Token, the Device Token is used to identify which devices should receive the message as a push notification. The Device token is combined with the published message and this Notification Package is sent from PubNub Mobile Push Gateway for APNs to the APN service for delivery.

Apple enforces that both APNs Push Certificates and Device Tokens must be created and used separately for Development and Production environments.

Push Notification Payload

A notification is a short message consisting of two major pieces of data: the Device Token and the Payload. The Apple Notification Payload contains information about how the system should alert the user as well as any custom data you provide.

The maximum size allowed for a notification payload is 256 bytes; Apple Push Notification Service will refuse any notification that exceeds this limit.

Each notification payload is composed of a JSON dictionary object (as defined by RFC 4627). This dictionary must contain another dictionary identified by the key aps. The aps dictionary contains one or more properties that specify the following actions:

  • An alert message to display to the user

  • A number to badge the application icon with

  • A sound to play

{
    "aps" : {
        "alert" : "This is a push notification",
        "badge" : 9,
        "sound" : "bingbong.aiff"
    },
}

As of today, when Mobile Push Gateway for APNs scans a message payload for APNs content, anything in the "aps" key will be sent, as well any key that follows, for example:

{
    "aps" : {
        "alert" : "This is a push notification",
        "badge" : 9,
        "sound" : "bingbong.aiff"
    },
    "also-sent" : { This portion of the message will also be sent to APNs as well },
    "me-too" : { This portion of the message will also be sent to APNs.},
}

This behavior will change in a future release so that only content contained in the "aps" tag is sent to APNS.

How Mobile Push Gateway for APNs Sends Messages to APNs.

Here is the sequence of events that occurs when a message is published to the Mobile Push Gateway for APNs enabled channel:

  1. A message is sent to a Mobile Push Gateway for APNs enabled channel that is associated with a particular PubNub subscribe_key.

  2. The message is received by PubNub Mobile Push Gateway for APNs (as well as any other subscribers on the channel).

  3. The PubNub Mobile Push Gateway for APNs identifies devices eligible for APNs delivery by selecting any devices with APNs Device Tokens registered to the PubNub channel.

  4. The PubNub Mobile Push Gateway for APNs selects the APNs specific content from the message payload.

  5. The PubNub Mobile Push Gateway for APNs then negotiates the authenticated connection to APNs service based on the application’s configured Apple Push Certificate and the message is then sent to the APN Server.

  6. The Apple Push Notification Server transports and routes the push notification to devices identified by APNs Device Tokens.

PubNub Mobile Push Gateway for APNs APIs

PubNub provides the following APIs to manage APNs message delivery to a device: enablePushNotificationsOnChannel:withDevicePushToken: - Registers the specified device token to receive push notifications on the given channel.
enablePushNotificationsOnChannels:withDevicePushToken: - Registers the specified device token to receive push notifications on the given channels.
disablePushNotificationsOnChannel:withDevicePushToken: - Disables push notifications for deviceToken on the channel.
disablePushNotificationsOnChannels:withDevicePushToken: - Disables push notifications for deviceToken on all channels specified.
requestPushNotificationEnabledChannelsForDevicePushToken: - Returns a list of all channels for which the Device Token is currently registered to receive push notifications.

Development Preparation - Apple Developer Program Portal

The following tasks need to be completed in the Apple Developer Program Portal to enable access to the Apple Push Notification service. These steps must be properly completed before beginning work with the PubNub Mobile Push Gateway for APNs.

The following steps in this section are specific to provisioning Apple Push Notification service. They are provided to make sure you get up and running with PubNub Mobile Push Gateway for APNs in as little time as possible.

  • Enable App ID for Push Notification

  • Obtain Development Push Certificate

  • Obtain Development Push Profile

Enable App ID for Push Notification

First we will create our App ID and enable push notifications:

  1. Log into the Apple Developer Program Portal

  2. In the box labeled iOS Apps, click on "Identifiers". Setting up PubNub Mobile Gateway

  3. If you have created an APP ID already, skip this step. Click the plus to register a new App ID. Enter a name (ex: PubNub APNS Tutorial), enter an explicit App ID (ex: com.mycompany.tutorial) then check the "Push Notifications" box under "App Services", then click "Submit". The new App ID is now registered to your account and can be used in your provisioning profiles. Setting up PubNub Mobile Gateway

  4. Now locate App ID under Identifiers → App IDs and click the name of your app on the right hand side. Setting up PubNub Mobile Gateway

  5. Now click "Edit" Setting up PubNub Mobile Gateway

  6. If the check box labeled "Push Notifications" is not enabled, click the box to enable it. Setting up PubNub Mobile Gateway

Generate and Upload a Certificate Signing Request

To configure push notifications for your iOS App ID, a Client SSL Certificate that allows PubNub Mobile Push Gateway for APNs to connect to the Apple Push Notification service is required. Each iOS application and corresponding App ID requires its own Client SSL Certificate. Follow the steps to generate your certificates below:

  1. Click "create certificate" in the Apple Developer Portal. Setting up PubNub Mobile Gateway

  2. Now in OSX open Applications → Utilities → Keychain Access.app on your Mac. Setting up PubNub Mobile Gateway

  3. Within the Keychain Access drop down menu, select Keychain Access → Certificate Assistant → Request a Certificate from a Certificate Authority. Setting up PubNub Mobile Gateway

  4. In the Certificate Information window, enter the following information:

    • In the User Email Address field, enter your email address.

    • In the Common Name field, create a name for your private key (e.g., John Doe Dev Key).

    • The CA Email Address field should be left empty.

    • In the "Request is" group, select the "Saved to disk" option.

    • Select a place to save the CSR and click done.

      Setting up PubNub Mobile Gateway

  5. Click "Continue" within Keychain Access to complete the CSR generating process. With the creation of your CSR, Keychain Access simultaneously generates a public and private key pair. Your private key is stored on your Mac in the login Keychain by default and can be viewed in the Keychain Access application under the "Keys" category. Your requested certificate will be the public half of your key pair.

  6. Click "Choose File" to select the CSR file you just created. It should be named something like "CertificateSigningRequest.certSigningRequest". Setting up PubNub Mobile Gateway

  7. Click "Generate" to upload your CSR file to the Apple Developer Portal. You should see the Certificate has been created and you can verify that the new certificate information is correct:

     Name: Apple Development iOS Push Services: com.pubnub.tutorial
     Type: APNs Development iOS
     Identifier ID: PubNub APNS Tutorial
     Expires:May 17, 2115
  8. Click "Download" to download your certificate to your Mac.

  9. Double click the .cer file (aps_development.cer) to install it in the Keychain Access.app. Make sure to also save a backup copy of your private and public keys somewhere secure. You should now see the new certificate in the Keychain Access.app under the Category "My_Certificates". You can double click the certificate to see more detailed information. Setting up PubNub Mobile Gateway

  10. Now click "Done" in the Apple Developer Portal, you should see your certificate listed as type "APNs Development iOS" Setting up PubNub Mobile Gateway

  11. Now in the Apple Developer Portal go to Identifiers → App IDs you should see your certificate information in the Push Notifications Box, under "Development SSL Certificate". Setting up PubNub Mobile Gateway

Download Provisioning Profile

  1. Click on Provision Profiles → All in the Apple Developer Portal. Setting up PubNub Mobile Gateway

  2. If you have already created a provisioning profile skip this step, otherwise click the plus sign to create a new profile. Setting up PubNub Mobile Gateway

  3. Click iOS App Development as the type of Provisioning Profile and click "Continue". Setting up PubNub Mobile Gateway

  4. Select your AppID in the drop down menu and click "Continue". Setting up PubNub Mobile Gateway

  5. Select the certificates you wish to include in this provisioning profile (For Example: Select All), then click "Continue". Setting up PubNub Mobile Gateway

  6. Select the devices you wish to include in this provisioning profile. To install an app signed with this profile on a device, the device must be included in the provisioning profile. If your device does not appear in the list, you’ll need to add the device under Devices → All and the add the device to provisioning profile. You will also need to enable development mode on the device in Xcode when you connect to it for the first time. Setting up PubNub Mobile Gateway

  7. Enter a Profile Name for the profile then click "Generate". Setting up PubNub Mobile Gateway

  8. Download and double click the following file (.mobileprovision) to install your Provisioning Profile.

  9. On your Mac in Xcode go to Preferences → Accounts → <your account> → View Details to verify the profile has been added to your Xcode when you double-clicked it. Setting up PubNub Mobile Gateway

Building your PubNub Application

With all of that busywork now out of the way, we’ll focus on getting our application running with PubNub. In this section we will:

  • Enable APNS in our PubNub Account.

  • Create our Project in Xcode.

  • Build & Test out our new realtime App.

Configuring Your PubNub Account For Push Notifications

Before enabling Push Notifications, you will need to convert the SSL Certificate you generated in the Apple Developer Portal for your application into PEM format.

  1. In Keychain Access → My Certificates, right click on the certificate and select "Export: …". Setting up PubNub Mobile Gateway

  2. Name the exported certificate with the .p12 (ex: myCert.p12) extension and save the file to your Mac.

  3. Now open a terminal window and issue the following openssl command to convert the .p12 file to a .pem format right from a Mac’s terminal window (remembering to replace with the cert (and key) names with your own):

     openssl pkcs12 -in <EXPORTED_CERT_NAME.p12> -out <PEM_CERT_NAME.pem> -nodes

    You can verify your cert was created correctly by running the following command and remembering to replace with the cert (and key) names with your own:

    openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert server_certificates_bundle_sandbox.pem -key server_certificates_bundle_sandbox.pem
  4. Login to PubNub Admin Portal.

  5. Select the PubNub application you want to enable Push Notifications for.

  6. Scroll down to Push Notifications and click on: You can change your APNS certificate here. Setting up PubNub Mobile Gateway

  7. Now browse to the location of the .pem file created in the previous step and select it as the cert to use for this application and click "Save". You’ll need to update this certificate in the event that you update the Push Certificate in the Apple Developer Portal. Setting up PubNub Mobile Gateway

  8. Make note of the application’s associated Subscribe and Publish keys as you will need to specify them in your application.

Create Your Xcode Project.

Now we will need to set up our new project in Xcode.

  1. You will first need to set up your Xcode project and link to the PubNub iOS SDK libraries. If haven’t already completed this task, follow the steps located here before proceeding to the next step.

    When creating the new project, remember to enter the App ID for Product Name that you created in the Apple Developer Portal. The Bundle Identifier (i.e.: com.mycompany.appid ) should match what was configured in the Apple Developer Portal.
  2. Open the application workspace that you have created in Xcode.

  3. In Xcode under General → Identity → Team if this isn’t set properly, you will get an error.

Getting Started with a Subscribe and Publish.

In this step we will borrow code from a previous tutorial that covered the basics of PubNub Data Streams. In that tutorial we explained how to subscribe and publish a message, so if you are unfamiliar with this you may want to try out that tutorial before proceeding further. If you’re already familiar simply copy and paste the code below into Xcode. You should also set the publishKey and subscribeKey to the values listed in the PubNub portal.

In this tutorial we’ll demonstrate how event handling in the iOS SDK is accomplished. Many of the following steps will show how to use different approaches including delegates, observers or code blocks to handle error conditions or take actions when specific events occur. This may seem redundant, since we are providing more than one way to accomplish the same thing. They are only provided so that you can quickly become familiar with the available options.

We will need to add the following into viewDidLoad in our ViewController.m:

 - (void)viewDidLoad
  {
      [super viewDidLoad];
 
      // Configure Keys
      PNConfiguration *myConfig = [PNConfiguration configurationForOrigin:@"pubsub.pubnub.com"
                                                               // Configure your keys!
                                                               publishKey:@"demo"
                                                             subscribeKey:@"demo"
                                                                secretKey:nil];
      // Define Channel
      PNChannel *my_channel = [PNChannel channelWithName:@"demo"
                                   shouldObservePresence:YES];
      // Set the Config
      [PubNub setConfiguration:myConfig];
      // Connect To PubNub.
      [PubNub connect];
 
      // Observer looks for connection events
      [[PNObservationCenter defaultCenter] addClientConnectionStateObserver:self withCallbackBlock:^(NSString *origin, BOOL connected, PNError *connectionError){
 
          if (connected)
          {
              NSLog(@"OBSERVER: Successful Connection!");
 
              // Subscribe on the channel
              [PubNub subscribeOnChannel:my_channel];
          }
          else if (!connected || connectionError)
          {
              NSLog(@"OBSERVER: Error %@, Connection Failed!", connectionError.localizedDescription);
          }
 
      }];
      // Observer looks for Subscribe events.
      [[PNObservationCenter defaultCenter] addClientChannelSubscriptionStateObserver:self withCallbackBlock:^(PNSubscriptionProcessState state, NSArray *channels, PNError *error){
 
          switch (state) {
              case PNSubscriptionProcessSubscribedState:
                  NSLog(@"OBSERVER: PNSubscriptionProcessSubscribedState: Subscribed to Channel: %@", channels[0]);
                  [PubNub sendMessage:[NSString stringWithFormat:@"Hello Everybody!" ] toChannel:my_channel ];
                  break;
              case PNSubscriptionProcessNotSubscribedState:
                  NSLog(@"OBSERVER: PNSubscriptionProcessNotSubscribedState: Not subscribed to Channel: %@, Error: %@", channels[0], error);
                  break;
              case PNSubscriptionProcessWillRestoreState:
                  NSLog(@"OBSERVER: PNSubscriptionProcessWillRestoreState: Will re-subscribe to Channel: %@", channels[0]);
                  break;
              case PNSubscriptionProcessRestoredState:
                  NSLog(@"OBSERVER: PNSubscriptionProcessRestoredState: Re-subscribed to Channel: %@", channels[0]);
                  break;
          }
      }];
      // Observer looks for message received events
      [[PNObservationCenter defaultCenter] addMessageReceiveObserver:self withBlock:^(PNMessage *message) {
          NSLog(@"OBSERVER: Channel: %@, Message: %@", message.channel.name, message.message);
      }];
 
      // Observer looks for unsubscribe events (this is optional)
      [[PNObservationCenter defaultCenter] addClientChannelUnsubscriptionObserver:self withCallbackBlock:^(NSArray *channel, PNError *error) {
          if ( error == nil )
          {
            NSLog(@"OBSERVER: addClientChannelUnsubscriptionObserver: Unsubscribed from Channel: %@", channel[0]);
            [PubNub subscribeOnChannel:my_channel];
          }
          else
          {
            NSLog(@"OBSERVER: addClientChannelUnsubscriptionObserver: Unsubscribed from Channel: %@, Error: %@", channel[0], error);
          }
      }];
      // Observers looks for message send events (this is optional)
      [[PNObservationCenter defaultCenter] addMessageProcessingObserver:self withBlock:^(PNMessageState state, id data){
 
          switch (state) {
              case PNMessageSent:
                  NSLog(@"OBSERVER: addMessageProcessingObserver:  Message Sent.");
                  break;
              case PNMessageSending:
                  NSLog(@"OBSERVER: addMessageProcessingObserver: Sending Message...");
                  break;
              case PNMessageSendingError:
                  NSLog(@"OBSERVER: addMessageProcessingObserver: ERROR: Failed to Send Message.");
                  break;
              default:
                  break;
          }
      }];
 }

Although they are optional, you can also add the following delegates to your AppDelegate.m file:

 - (void)pubnubClient:(PubNub *)client didSendMessage:(PNMessage *)message{
    NSLog(@"DELEGATE: client sent message: %@", message);
 }
 
 - (void)pubnubClient:(PubNub *)client didReceiveMessage:(PNMessage *)message {
     NSLog(@"DELEGATE: Message received.");
 }
 
 - (void)pubnubClient:(PubNub *)client didConnectToOrigin:(NSString *)origin {
     NSLog(@"DELEGATE: Connected to  origin: %@", origin);
 }
 
 - (void)pubnubClient:(PubNub *)client didSubscribeOnChannels:(NSArray *)channels {
     NSLog(@"DElEGATE: Subscribed to channel:%@", channels);
 }
 
 - (void)pubnubClient:(PubNub *)client didUnsubscribeOnChannels:(NSArray *)channels {
     NSLog(@"DELEGATE: Unsubscribed from channel:%@", channels);
 }

Once you have your ViewController.m and AppDelegate.m setup, try running your simulator in Xcode. You should see the following output appear in the console:

 tutorial [78350:60b] DELEGATE: Connected to  origin: pubsub.pubnub.com
 tutorial [78350:60b] OBSERVER: Successful Connection!
 tutorial [78350:60b] DElEGATE: Subscribed to channel:(
     "PNChannel(0x915cf00) demo"
 )
 PubNub Tutorial - Data Streams[78350:60b] OBSERVER: Subscribed to Channel: PNChannel(0x915cf00) demo
 tutorial[22132:60b] OBSERVER: Message Sent.
 tutorial[22132:60b] OBSERVER: Channel: demo, Message: Hello Everybody!

If your application has successfully subscribed and published a message to the PubNub Real-Time Network, its time to get to work adding the push notification code into our app.

Setting Up Push Notifications

In this section we will make the needed changes to enable the client to receive push notifications. This involves editing a few different files which we will cover one at a time.

AppDelegate.h

In AppDelegate.h, define the dToken NSData object property.

 //
 //  AppDelegate.h
 //  tutorial
 //
 //  Created by Thomas Burger on 5/7/14.
 //  Copyright (c) 2014 PubNub. All rights reserved.
 //
 
 #import <UIKit/UIKit.h>
 
 @interface AppDelegate : UIResponder <UIApplicationDelegate, PNDelegate>
 
 @property (strong, nonatomic) UIWindow *window;
 
 // #1 Define there properties
 @property NSData *dToken;
 
 @end
AppDelegate.m

In AppDelegate.m we’ll need to add a few different delegates to:

  • Register the client APNs

  • Retrieve the deviceToken

  • Process the incoming push notification

  • Perform any necessary event handling

 //
 //  AppDelegate.m
 //  tutorial
 //
 //  Created by Thomas Burger on 5/7/14.
 //  Copyright (c) 2014 PubNub. All rights reserved.
 //
 
 #import "AppDelegate.h"
 
 @implementation AppDelegate
 
 // #1 synthesize vars
 @synthesize dToken;
 
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
     // #2 Register client for push notifications
     [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
 
     [PubNub setDelegate:self];
 
     return YES;
 }
 
 // #3 add delegate to get the deviceToken from the APNs callback didRegisterForRemoteNotificationsWithDeviceToken
 - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
   NSLog(@"DELEGATE: Device Token is: %@", deviceToken);
 
     dToken = deviceToken;
 }
 
 
 // #4 add delegate to report any errors getting the deviceToken (optional)
 - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
   NSLog(@"DELEGATE: Failed to get token, error: %@", error);
 }
 
 
 // #5 Process received push notification
 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
 {
     NSString *message = nil;
     id alert = [userInfo objectForKey:@"aps"];
     if ([alert isKindOfClass:[NSString class]]) {
         message = alert;
     } else if ([alert isKindOfClass:[NSDictionary class]]) {
         message = [alert objectForKey:@"alert"];
     }
     if (alert) {
         UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:message
                                                             message:@"Sent Via PubNub Mobile Gateway."  delegate:self
                                                   cancelButtonTitle:@"Thanks PubNub!"
                                                   otherButtonTitles:@"Send Me More!", nil];
         [alertView show];
     }
 }
 
 // #6 Add PubNub delegate to catch when channel in enabled with APNs
 - (void)pubnubClient:(PubNub *)client didEnablePushNotificationsOnChannels:(NSArray *)channels {
 
    // This delegate method is called if push notifications for all channels are successfully enabled.
    // “channels” will contain the array of channels which have push notifications enabled.
 
    NSLog(@"DELEGATE: Enabled push notifications on channels: %@", channels);
 
 }
 
 // #7 Add PubNub delegate to catch when apns receives a push notification for a channel
 - (void)pubnubClient:(PubNub *)client didReceivePushNotificationEnabledChannels:(NSArray *)channels {
 
     // This delegate method is called when the client successfully receives push notifications for a channel.
     // “channels” will contain the array of channels which received push notifications.
 
     NSLog(@"DELEGATE: Received push notifications for these enabled channels: %@", channels);
 }
 
 // #8 Add PubNub delegate to catch when client fails to enable apns for channel
 - (void)pubnubClient:(PubNub *)client pushNotificationEnableDidFailWithError:(PNError *)error {
 
     // This delegate method is called when an error occurs on enabling push notifications for all channels.
     // “error” will contain the details of the error.
 
     NSLog(@"DELEGATE: Failed push notification enable. error: %@", error);
 
 }
 
 // #9 Add PubNub delegate to catch when apns is disabled for a channel (optional)
 - (void)pubnubClient:(PubNub *)client didDisablePushNotificationsOnChannels:(NSArray *)channels {
 
     // This delegate method is called when push notifications for all channels are successfully disabled.
     // “channels” will contain the array of channels which have push notifications disabled.
 
     NSLog(@"DELEGATE: Disabled push notifications on channels: %@", channels);
 }
 
 // #10 Add PubNub delegate to catch when apns fails to be disabled for a channel (optional)
 - (void)pubnubClient:(PubNub *)client pushNotificationDisableDidFailWithError:(PNError *)error {
 
 
     // This delegate method is called when an error occurs on disabling push notifications for all channels.
     // “error” will contain the details of the error.
 
     NSLog(@"DELEGATE: Failed to disable push notifications because of error: %@", error);
 }
 
 // #11 Add PubNub delegate to catch when apns disabled for all channels (optional)
 - (void)pubnubClientDidRemovePushNotifications:(PubNub *)client {
 
     //This delegate method is called when push notifications for all channels are successfully removed.
 
    NSLog(@"DELEGATE: Removed push notifications from all channels");
 }
 
 // #12 Add delegate to catch when apns fails to be disabled for channels (optional)
 - (void)pubnubClient:(PubNub *)client pushNotificationsRemoveFromChannelsDidFailWithError:(PNError *)error {
 
     // This delegate method is called when an error occurs on removing push notifications for all channels.
     // “error” will contain the details of the error.
 
     NSLog(@"DELEGATE: Failed remove push notifications from channels because of error: %@",error);
 }
 
 // #13 Add PubNub delegate to catch when apns fails to receive a push notification for some reason (optional)
 - (void)pubnubClient:(PubNub *)client pushNotificationEnabledChannelsReceiveDidFailWithError:(PNError *)error {
 
     // This delegate method is called when the client fails to receive push notifications for a channel.
     // “error” will contain the details of the error.
     NSLog(@"DELEGATE: Failed to receive list of channels because of error: %@", error);
 }
ViewController.h

In ViewController.h we’ll just need to define the deviceToken NSData object property.

 //
 //  ViewController.h
 //  tutorial
 //
 //  Created by Thomas Burger on 5/7/14.
 //  Copyright (c) 2014 PubNub. All rights reserved.
 //
 
 #import <UIKit/UIKit.h>
 
 @interface ViewController : UIViewController
 
 // #1 Define the deviceToken property.
 @property NSData *deviceToken;
 @end
ViewController.m

For ViewConroller.m we need to accomplish the following:

  1. Import AppDelegate

  2. synthesize deviceToken variable

  3. Define AppDelegate

  4. Pass the deviceToken from the Delegate

  5. Double check we’ve passed the token properly

  6. If we have the device token enable apns for our channel if we aren’t already enabled.

  7. Add an observer to catch when push notifications are enabled.

  8. Add an observer to catch if push notifications are disabled.

  9. Add an observer to catch when requestPushNotificationEnabledChannelsForDevicePushToken is returned

 //
 //  ViewController.m
 //  tutorial
 //
 //  Created by Thomas Burger on 5/7/14.
 //  Copyright (c) 2014 PubNub. All rights reserved.
 //
 
 #import "ViewController.h"
 
 // #1 Import AppDelegate
 #import "AppDelegate.h"
 
 @interface ViewController ()
 
 @end
 
 @implementation ViewController
 
 
 // #2 initialize deviceToken variable
 @synthesize deviceToken;
 
 - (void)viewDidLoad
 {
     [super viewDidLoad];
 
 
     PNConfiguration *myConfig = [PNConfiguration configurationForOrigin:@"pubsub.pubnub.com"
                                                              publishKey:@"pub-c-74607941-7ff9-4759-bf51-6bce24bbea32"
                                                            subscribeKey:@"sub-c-9faaaf2e-1f2e-11e3-a5f4-02ee2ddab7fe"
                                                               secretKey:nil];
 
     PNChannel *my_channel = [PNChannel channelWithName:@"demo"
                                  shouldObservePresence:YES];
 
     [PubNub setConfiguration:myConfig];
     [PubNub connect];
 
     [[PNObservationCenter defaultCenter] addClientConnectionStateObserver:self withCallbackBlock:^(NSString *origin, BOOL connected, PNError *connectionError){
 
         if (connected)
         {
             NSLog(@"OBSERVER: Successful Connection!");
 
             // Subscribe on connect
             [PubNub subscribeOnChannel:my_channel];
 
             // #3 Define AppDelegate
             AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
 
             // #4 Pass the deviceToken from the Delegate
             deviceToken = appDelegate.dToken;
 
             // #5 Double check we've passed the token properly
             NSLog(@"Device token received: %@", deviceToken);
 
             // #6 If we have the device token, enable apns for our channel if it isn't already enabled.
             if (deviceToken) {
 
                 // APNS enabled already?
                 [PubNub requestPushNotificationEnabledChannelsForDevicePushToken:deviceToken
                                                      withCompletionHandlingBlock:^(NSArray *channels, PNError *error){
                   if (channels.count == 0 )
                   {
                       NSLog(@"BLOCK: requestPushNotificationEnabledChannelsForDevicePushToken: Channel: %@ , Error %@",channels,error);
 
                       // Enable APNS on this Channel with deviceToken
                       [PubNub enablePushNotificationsOnChannel:my_channel
                                            withDevicePushToken:deviceToken
                                     andCompletionHandlingBlock:^(NSArray *channel, PNError *error){
                                         NSLog(@"BLOCK: enablePushNotificationsOnChannel: %@ , Error %@",channel,error);
                       }];
                   }
                 }];
             }
         }
         else if (!connected || connectionError != nil )
         {
             NSLog(@"OBSERVER: Error %@, Connection Failed!", connectionError.localizedDescription);
         }
 
     }];
     [[PNObservationCenter defaultCenter] addClientChannelSubscriptionStateObserver:self withCallbackBlock:^(PNSubscriptionProcessState state, NSArray *channels, PNError *error){
 
         switch (state) {
             case PNSubscriptionProcessSubscribedState:
                 NSLog(@"OBSERVER: Subscribed to Channel: %@", channels[0]);
                 [PubNub sendMessage:[NSString stringWithFormat:@"This is an Apple Push Notification!" ] toChannel:my_channel ];
                 break;
             case PNSubscriptionProcessNotSubscribedState:
                 NSLog(@"OBSERVER: Not subscribed to Channel: %@, Error: %@", channels[0], error);
                 break;
             case PNSubscriptionProcessWillRestoreState:
                 NSLog(@"OBSERVER: Will re-subscribe to Channel: %@", channels[0]);
                 break;
             case PNSubscriptionProcessRestoredState:
                 NSLog(@"OBSERVER: Re-subscribed to Channel: %@", channels[0]);
                 break;
         }
     }];
     [[PNObservationCenter defaultCenter] addMessageProcessingObserver:self withBlock:^(PNMessageState state, id data){
 
         switch (state) {
             case PNMessageSent:
                 NSLog(@"OBSERVER: Message Sent.");
                 break;
             case PNMessageSending:
                 NSLog(@"OBSERVER: Sending Message...");
                 break;
             case PNMessageSendingError:
                 NSLog(@"OBSERVER: ERROR: Failed to Send Message.");
                 break;
             default:
                 break;
         }
     }];
     [[PNObservationCenter defaultCenter] addMessageReceiveObserver:self withBlock:^(PNMessage *message) {
         NSLog(@"OBSERVER: Channel: %@, Message: %@", message.channel.name, message.message);
     }];
 
     // #7 Add an observer to catch when push notifications are enabled. (optional)
     [[PNObservationCenter defaultCenter] addClientPushNotificationsEnableObserver:self
                                                                 withCallbackBlock:^(NSArray *channels, PNError *error){
                                                                     NSLog(@"OBSERVER: addClientPushNotificationsEnableObserver: channels: %@ Error: %@.", channels, error);
                                                                 }];
     // #8 Add an observer to catch if push notifications are disabled. (optional)
     [[PNObservationCenter defaultCenter] addClientPushNotificationsDisableObserver:self
                                                                  withCallbackBlock:^(NSArray *channels, PNError *error){
                                                                      NSLog(@"OBSERVER: addClientPushNotificationsDisableObserver: channels: %@, error: %@ ", channels, error);
 
                                                                  }];
     // #9 Add an observer to catch when requestPushNotificationEnabledChannelsForDevicePushToken is returned (optional)
     [[PNObservationCenter defaultCenter] addClientPushNotificationsEnabledChannelsObserver:self
                                                                          withCallbackBlock:^(NSArray *channels, PNError *error){
                                                                     NSLog(@"OBSERVER: addClientPushNotificationsEnabledChannelsObserver: channels: %@ error: %@" ,channels,error);
                                                                           }];
 }
 - (void)didReceiveMemoryWarning
 {
     [super didReceiveMemoryWarning];
     // Dispose of any resources that can be recreated.
 }
 
 @end

Testing The Client

If you’ve made it this far, you should be ready to see a push notification fire; get ready for your moment of triumph.

Running the application in the simulator.

The first step is to run the app in the simulator, but don’t get too excited just yet: we can’t actually receive push notifications in the simulator, we’ll need a real iOS device for that. For now we’ll just make sure that our code is working properly. You should be able to see that we are getting getting our deviceToken returned from the APNs service. That’s actually a good sign!

In the Xcode console you should see the following messages:

 tutorial[21965:60b] DELEGATE: Failed to get token, error: Error Domain=NSCocoaErrorDomain Code=3010 "remote notifications are not supported in the simulator" UserInfo=0x1096970d0 {NSLocalizedDescription=remote notifications are not supported in the simulator}
 tutorial[21965:60b] OBSERVER: Successful Connection!
 tutorial[21965:60b] Device token received: (null)
 tutorial[21965:60b] OBSERVER: Subscribed to Channel: PNChannel(0x109417700) demo
 tutorial[21965:60b] OBSERVER: Sending Message...
 tutorial[21965:60b] OBSERVER: Message Sent.
 tutorial[21965:60b] OBSERVER: Channel: demo, Message: This is an Apple Push Notification!
Receive Push Notification With Mobile Device.

Since push notifications cannot be received in the simulator, you will now need to connect your iOS device to Xcode and also remember to provision your device in the drop down menu before running the app once more in Xcode.

The first time you run the app on the iOS device, you will be prompted to allow push notifications for this application; click OK. Now you should receive an alert containing our message appear on your device. Finally… our moment of triumph!

Receive Push Notification Sent From Remote Client.

Now to make ourselves feel even better, we can test to see if push notifications will be received on the iOS device when messages are published to the same channel by remote clients. We’ll use the PubNub Developer Console to simulate a remote client and send a properly formatted APN message.

Below is our sample message, formatted specifically for APNs:

{
      "aps" : {
        "alert": "If you are reading this, you should have just received an alert.",
        "badge": 9,
        "sound": "bingbong.aiff"
      }
}

A simple string should work as well.

Here is all we need to do:

  1. Login to PubNub Developer Console

  2. Enter your publish and subscribe keys.

  3. Enter the Channel Name.

  4. Copy and Paste the above message into the message field and click to send the message.

Once you’ve sent the message from the console you should the see an alert containing the above message appear on your iOS device. Success once more.

Retrieve Push Notification with App in the background.

For our final act, we’ll see if when we close the application and open up a different app on your iOS device, do we still receive push notifications? You can repeat the above steps in the PubNub Developer Console and you’ll see, it still works even with the application in the background.

Congratulations - you’ve just leveled up considerably. You can now send and receive APNs to devices all over the world. Feel the burn…

Loading...