Saturday, March 17, 2012

Get device token for apple push notifications in sencha touch and phone gap

Hello,

Recently I was working on Apple push notifications with sencha touch and phonegap project. Requirement was to get device token in JavaScript file so that it can be sent to server for getting push notifications. For that first thing we need to do is register device to get Push notifications.

Please make sure that you have real apple device like iPad, iPhone or iPod touch to test this. This will not work in Simulator.

To register device for push notifications add following in your AppDelegate.m file.  Find method


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

Also add following line to define token variable.


@synthesize token;


and add following code at end of the method.


NSLog(@"Registering for push notifications...");    
    [[UIApplication sharedApplication] 
     registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeAlert | 
      UIRemoteNotificationTypeBadge | 
      UIRemoteNotificationTypeSound)];

This will register device for getting push notifications. Please make sure that you have added provisioning profile which configured with non wild card app id and app is configured to receive  push notifications in your development portal. Also you need valid developer certificate.

After that you need to add following methods at end of the file.

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 

    
    self.token = [[[[deviceToken description]
                    stringByReplacingOccurrencesOfString: @"<" withString: @""]
                   stringByReplacingOccurrencesOfString: @">" withString: @""]
                  stringByReplacingOccurrencesOfString: @" " withString: @""];
    
    NSLog(@"My token is: %@", self.token);
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
    
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];
    NSLog(str);    
    
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    
    for (id key in userInfo) {
        NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
    }    
    
}


This will get device token and store it to token. Now to send this token to JavaScript we will create a phonegap plugin. Please make sure that this code will work with Phonegap version 1.5.0. They named this version as Cardova.

First create folder inside plugins folder of your project folder and name it as PushToken and add two files to it PushToken.m and PushToken.h

Open PushToken.h file and add following code to it.



#import <Foundation/Foundation.h>
#import <Cordova/CDVPlugin.h>

@interface PushToken : CDVPlugin{
    
    NSString* callbackID;  
}

@property (nonatomic, copy) NSString* callbackID;

- (void) getToken:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;

@end



Now open PushToken.m file and add following code to it.

#import "PushToken.h"
#import "AppDelegate.h"

@implementation PushToken

@synthesize callbackID;

-(void)getToken:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options  {
    self.callbackID = [arguments pop];
    
    NSString *token = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).token;
    
    CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:[token stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    
    if(token.length != 0)
    {
        [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
    }else {    
        [self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]];
    }
}

@end

Now we have to map this plugin. For that open Cordova.plist file and following key value pair to it.

PushToken : PushToken

After that open AppDelegate.h file and add following line to it.

@property (retain, nonatomic) NSString* token;

That's it of phonegap side now we have to create JavaScript file form where we will execute this plugin code. Create JavaScript file with name PushToken.js and add it to www folder. Add following code to it.

var PushToken = {
    getToken: function(types, success, fail) {
        return Cordova.exec(success, fail, "PushToken", "getToken", types);
    }
};

Add link of this JavaScript file to your index.html page after phonegap JavaScript file. To get device token wherever you want use following code.


PushToken.getToken(     
                     ["getToken"] ,           
                     function(token) {
                              global.token = token; 
                     },
                     function(error) {
                              console.log("Error : \r\n"+error);      
                     }
          );

That's it and you have your device token.




21 comments:

  1. Great output. Have you already release an app in app store? I'm currently working on a app and I am wondering how apple will handle phonegap apps...

    cheers
    chris

    ReplyDelete
  2. No app is currently under development. Apple store accepts phonegap app.

    ReplyDelete
  3. grate article ,,,it helps me a lot.......

    ReplyDelete
  4. Hi Hiren,

    Currently, I am facing issue when I am sending any notification message like "Test němьci Message" than I will receive "Test n?m?ci Message" in my Ipad.

    Can you please help me on this point.

    ReplyDelete
  5. Can this work on Sencha Touch 2 as well?

    ReplyDelete
  6. When I add the @synthasize token command I get the following error
    "Unexpected '@' in program. Here is where I added it. Any ideas?

    - (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    {
    @synthesize token;

    ReplyDelete
  7. Can't seem to figure out where to add the "@synthesize token;"
    No experience with this kind of stuff whatsoever

    ReplyDelete
    Replies
    1. put that line in AppDelegate.m file right above the line that contains didFinishLaunchingWithOptions. It will give you errors until you add the '@property (retain, nonatomic) NSString* token;
      ' to the AppDelegate.h file.

      Delete
  8. HI,
    nice this is what I need.
    However, I follow above and I can see the token in console.Then I make call in order to display it in javascript, seems the getToken function never calls. I put NSLog(@"plugin"); inside
    -(void)getToken:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
    self.callbackID = [arguments pop];
    NSLog(@"plugin");
    }
    it never show in console and it means this function never called.
    So what is wrong??

    Many thanks

    ReplyDelete
  9. Hi
    i get this error while trying to use the plugin
    i have added PushToken in the plist.

    ERROR: Plugin 'PushToken' not found, or is not a CDVPlugin. Check your plugin mapping in Cordova.plist.
    FAILED pluginJSON = {"className":"PushToken","methodName":"getToken","arguments":["PushToken2","getToken

    ReplyDelete
    Replies
    1. I get the same error!

      Delete
    2. I have solved this problem.

      First, don't create PushToken folder. Put PushToken.m and PushToken.h right into Plugins folder, as it said in README.

      In the second, you need to add key-value pair to Cordova.plist not in the root, but in Plugins dictionary.

      Delete
  10. Absolute life-saver, thanks!

    ReplyDelete
  11. I have not seen any tips for the sencha touch application. Can you please tell me how to get uuid in sencha touch application?

    ReplyDelete
    Replies
    1. You can use phonegap. it gives you device object
      var txtUUID = device.uuid;

      Delete
  12. i'm getting ERROR: Plugin 'PushToken' not found, or is not a CDVPlugin. Check your plugin mapping in Cordova.plist, tried to put directly in plugins folder but do no work.

    ReplyDelete
  13. hey, very informative.
    But in my case, I am getting null value. its going in failure method. Can you please help me out with this.

    ReplyDelete
  14. Hi how can i ger device token id from sencha using js ?

    ReplyDelete
  15. Plugin 'PushToken' not found, or is not a CDVPlugin. Check your plugin mapping in config.xml. I am adding PushToken.h and PushToken.m in plugin folder and key-value pair in cordova.plist.Still it display same error.Please help me as soon as possible thanks

    ReplyDelete