Apple Push Notification Services Tutorial: Part 1/3

Step 1: Prepare the App to receive Push Notifications

In this tutorial I will explain all steps how to make an app for production that can receive Push Notifications. Basically there are 3 steps that must be explained:

  • Prepare the app to receive Push Notifications
    1. Login Developer Account & modify/enable app ID to receive PNs
    2. Use your new and PN enabled provisioning profile
    3. Modify AppDelegate to handle PNs
  • Do some sorcery on your terminal
    1. Generate cert & key files used by your php script to comm. with APNS
    2. Make some nice and easy PHP scripts to send messages right away
  • Build/modify provided Database-creation code to save device information
    1. Build up database to receive user information
    2. Take it all together – done!

Advertisement:

white,pages,yellow,tracker,search,find,gps,mobile,411,ringtone,business,911,likes,follower,locator

The first iPhone App ever that finds out who’s calling you before you answer the phone.


 

Step 1: Prepare the app to receive Push Notifications

OK, let’s begin! Login to your Developer Account: http://developer.apple.com

As you can see, if you go to the section App IDs, you can see all of your App IDs in a list. then you should click on “Configure” where you want to enable Push notifications.

Then you’ll see something like this below:

… click on “Configure” again (we use here for example “Production Push SSL Certificate” to enable it already for the App Store production version) and follow all the instructions on the screen. Upload your “CertificateSigningRequest.certSigningRequest” that you just generated on your Mac and wait.

Once you have accomplished this steps, download your “aps_production.cer” and save it into a folder on your desktop:

Now you can regenerate your Provisioning profile! You must do this step to guarantee that your App is able to receive Push Notifications, don’t forget!

Now we want to enable our App to receive Push Notifications… open your project and edit your AppDelegate.m like this in the method “-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}”:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{   
    // Add registration for remote notifications
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationType)(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];

    // do all your stuff here

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];

    [self.window makeKeyAndVisible];

    return YES;
}

 

OK, now we need some more stuff that you can copy/paste and modify with your information:

 

 /*
 * ------------------------------------------------------------------------------------------
 *  BEGIN APNS CODE
 * ------------------------------------------------------------------------------------------
 */

/**
 * Fetch and Format Device Token and Register Important Information to Remote Server
 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {

#if !TARGET_IPHONE_SIMULATOR

    // Get Bundle Info for Remote Registration (handy if you have more than one app)
    NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"];
    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];

    // Check what Notifications the user has turned on.  We registered for all three, but they may have manually disabled some or all of them.
    NSUInteger rntypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];

    // Set the defaults to disabled unless we find otherwise...
    NSString *pushBadge = @"disabled";
    NSString *pushAlert = @"disabled";
    NSString *pushSound = @"disabled";

    // Check what Registered Types are turned on. This is a bit tricky since if two are enabled, and one is off, it will return a number 2... not telling you which
    // one is actually disabled. So we are literally checking to see if rnTypes matches what is turned on, instead of by number. The "tricky" part is that the
    // single notification types will only match if they are the ONLY one enabled.  Likewise, when we are checking for a pair of notifications, it will only be
    // true if those two notifications are on.  This is why the code is written this way
    if(rntypes == UIRemoteNotificationTypeBadge){
        pushBadge = @"enabled";
    }
    else if(rntypes == UIRemoteNotificationTypeAlert){
        pushAlert = @"enabled";
    }
    else if(rntypes == UIRemoteNotificationTypeSound){
        pushSound = @"enabled";
    }
    else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)){
        pushBadge = @"enabled";
        pushAlert = @"enabled";
    }
    else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)){
        pushBadge = @"enabled";
        pushSound = @"enabled";
    }
    else if(rntypes == ( UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)){
        pushAlert = @"enabled";
        pushSound = @"enabled";
    }
    else if(rntypes == ( UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)){
        pushBadge = @"enabled";
        pushAlert = @"enabled";
        pushSound = @"enabled";
    }

    // Get the users Device Model, Display Name, Unique ID, Token & Version Number
    UIDevice *dev = [UIDevice currentDevice];
    NSString *deviceUuid = dev.uniqueIdentifier;
    NSString *deviceName = dev.name;
    NSString *deviceModel = dev.model;
    NSString *deviceSystemVersion = dev.systemVersion;

    // Prepare the Device Token for Registration (remove spaces and < >)
    NSString *deviceToken = [[[[devToken description]
                               stringByReplacingOccurrencesOfString:@"<"withString:@""]
                              stringByReplacingOccurrencesOfString:@">" withString:@""]
                             stringByReplacingOccurrencesOfString: @" " withString: @""];

    // Build URL String for Registration
    // !!! CHANGE "www.mywebsite.com" TO YOUR WEBSITE. Leave out the http://
    NSString *host = @"www.YOURDOMAIN.com";

    // !!! CHANGE "/apns.php?" TO THE PATH TO WHERE apns.php IS INSTALLED
    // !!! ( MUST START WITH / AND END WITH ? ).
    // !!! SAMPLE: "/path/to/apns.php?"
    NSString *urlString = [@"/pushservice/apns.php?"stringByAppendingString:@"task=register"];

    NSLog(@"devicetoken length: %i", [deviceToken length]);
    urlString = [urlString stringByAppendingString:@"&appname="];
    urlString = [urlString stringByAppendingString:appName];
    urlString = [urlString stringByAppendingString:@"&appversion="];
    urlString = [urlString stringByAppendingString:appVersion];
    urlString = [urlString stringByAppendingString:@"&deviceuid="];
    urlString = [urlString stringByAppendingString:deviceUuid];
    urlString = [urlString stringByAppendingString:@"&devicetoken="];
    urlString = [urlString stringByAppendingString:deviceToken];
    urlString = [urlString stringByAppendingString:@"&devicename="];
    urlString = [urlString stringByAppendingString:deviceName];
    urlString = [urlString stringByAppendingString:@"&devicemodel="];
    urlString = [urlString stringByAppendingString:deviceModel];
    urlString = [urlString stringByAppendingString:@"&deviceversion="];
    urlString = [urlString stringByAppendingString:deviceSystemVersion];
    urlString = [urlString stringByAppendingString:@"&pushbadge="];
    urlString = [urlString stringByAppendingString:pushBadge];
    urlString = [urlString stringByAppendingString:@"&pushalert="];
    urlString = [urlString stringByAppendingString:pushAlert];
    urlString = [urlString stringByAppendingString:@"&pushsound="];
    urlString = [urlString stringByAppendingString:pushSound];

    // Register the Device Data
    // !!! CHANGE "http" TO "https" IF YOU ARE USING HTTPS PROTOCOL
    NSURL *url = [[NSURL alloc] initWithScheme:@"http" host:host path:urlString];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSLog(@"Register URL: %@", url);
    NSLog(@"Return Data: %@", returnData);

#endif
}

/**
 * Failed to Register for Remote Notifications
 */
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

#if !TARGET_IPHONE_SIMULATOR

    NSLog(@"Error in registration. Error: %@", error);

#endif
}

/**
 * Remote Notification Received while application was open.
 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

#if !TARGET_IPHONE_SIMULATOR

    NSLog(@"remote notification: %@",[userInfo description]);
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];

    NSString *alert = [apsInfo objectForKey:@"alert"];
    NSLog(@"Received Push Alert: %@", alert);

    NSString *sound = [apsInfo objectForKey:@"sound"];
    NSLog(@"Received Push Sound: %@", sound);
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

    NSString *badge = [apsInfo objectForKey:@"badge"];
    NSLog(@"Received Push Badge: %@", badge);
    application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];

#endif
}

/*
 * ------------------------------------------------------------------------------------------
 *  END APNS CODE
 * ------------------------------------------------------------------------------------------
 */

 

Now you are almost done with your code in your App! Don’t forget to modify the line:

NSString *host = @"www.YOURDOMAIN.com";

… and…

    NSString *urlString = [@"/pushservice/apns.php?"stringByAppendingString:@"task=register"];

(if you want to put the “apns.php” file into another folder on your webserver! Otherwise leave this)

 

Continue reading:
APNS – Tutorial: how to send Push Notifications to my iPhone / iPad App – Part 2

 

 

2 comments

  1. Qaiser Abbas says:

    I have followed all step

    Very Nice

    But still getting one last error

    That is not adding device info to data table

    NSURL *url = [[NSURL alloc] initWithScheme:@”http” host:host path:urlString];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSLog(@”Register URL: %@”, url);
    NSLog(@”Return Data: %@”, returnData);

    Here it returns Null

    ??
    i dont know why its happening

    but when i paste same url in the browser and hit enter it works and device info added to table

    • admin says:

      Hi Quaiser

      Please try to add this:

      urlString = [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];

      before:

      NSURL *url = [[NSURL alloc] initWithScheme:@”http” host:host path:urlString];

      And try again… maybe that’s the problem.

      Cheers

Leave a Reply

Your email address will not be published. Required fields are marked *


*