Suggestion on how to link APN's device token to a registered user (through phonegap or UIWebView)

前端 未结 3 1073
南旧
南旧 2021-02-01 11:52

Similar question here: jQueryMobile, Phonegap and Device Token - iOS

The scenario is, I have this PhoneGap web based application, and the native iOS help me registered t

相关标签:
3条回答
  • 2021-02-01 11:55

    Ok, I finally made a plugin that seems to work

    1 - Make sure your PhoneGap Xcode project has been updated for the iOS 4 SDK.

    2 - Create a PushToken folder in your Plugins folder add the following PushToken.m and PushToken.h files to it and then drag the folder to the Plugin folder in XCode, using "Create groups for any added folders"

    3 - Add the PushToken.js files to your www folder on disk, and add reference(s) to the .js files as tags in your html file(s)

    4 - Add new entry with key PushToken and string value PushToken to Plugins in PhoneGap.plist

    PushToken.h

    #import <Foundation/Foundation.h>
    #import <PhoneGap/PGPlugin.h>
    
    @interface PushToken : PGPlugin{
    
        NSString* callbackID;  
    }
    
    @property (nonatomic, copy) NSString* callbackID;
    
    - (void) getToken:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
    
    @end
    

    PushToken.m

    #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;
        PluginResult* pluginResult = [PluginResult resultWithStatus:PGCommandStatus_OK messageAsString:[token stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    
        if(token.length != 0)
        {
            [self writeJavascript: [pluginResult toSuccessCallbackString:self.callbackID]];
        }else {    
            [self writeJavascript: [pluginResult toErrorCallbackString:self.callbackID]];
        }
    }
    
    @end
    

    PushToken.js

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

    How to use

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

    AppDelegate.h

    @interface AppDelegate : PhoneGapDelegate {
        NSString* invokeString;
        NSString* token;
    }
    
    @property (copy)  NSString* invokeString;
    @property (retain, nonatomic) NSString* token;
    

    AppDelegate.m

    - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
    {
        self.token = [[[[deviceToken description]
                             stringByReplacingOccurrencesOfString: @"<" withString: @""]
                            stringByReplacingOccurrencesOfString: @">" withString: @""]
                           stringByReplacingOccurrencesOfString: @" " withString: @""];
    
        NSLog(@"My token is: %@", self.token);
    }
    

    I made it work on PhoneGap 1.1

    Hope this helps

    0 讨论(0)
  • 2021-02-01 11:56

    The previous answers are really great ways to solve this problem and they do it in a very formal fashion. However, if you want a quick and dirty method of solving the problem, you can simply do this:

    at the bottom of didRegisterForRemoteNotificationsWithDeviceToken add

    NSString* jsString = [NSString stringWithFormat:@"var deviceToken = \"%@\";", deviceToken];
    [self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
    

    In your javascript

    deviceId = (typeof deviceToken !== "undefined") ? deviceToken : null;
    
    0 讨论(0)
  • 2021-02-01 11:59

    For the sake of completeness, this is my solution after using @TDeBailleul solution. Ported over to Cordova. (Tested on iOS only. After I have finished Android version I will post a plugin for this:

    Environment

    • Cordova 1.5.0 (Formerly PhoneGap)
    • Xcode 4.3.1
    • iOS 5.1
    • Mac OS X 10.7.3
    • Do not use Automatic Reference Counting (ARC) to avoid compilation error
    • Go through this freaking long tutorial to have your Push Notification certificate ready

    Working Flow

    1. [Native] Application started - APN registration started and device_token is received at server side
    2. [Native] Application store the token in AppDelegate, and to get the token, use the PushToken in the following codes
    3. [WebView] Whenever a user is login or signup, the token will be called through Cordova (formerly PhoneGap) plugin, hashed and being sent over to the server to do a sign in, matching and link up the user to a particular device.

    So below is my complete working codes that do the native pulling of token. Server part is nothing but just linking accounts to devices. You should know how to do it through your favourite server side application.

    AppDelegate.h

    @interface AppDelegate : NSObject < UIApplicationDelegate, UIWebViewDelegate, CDVCommandDelegate > {
        ...
        NSString* token;
        ...
    }
    ...
    ...
    ...
    @property (retain, nonatomic) NSString* token;
    

    AppDelegate.m

    Note: I'm a Obj-C newbie and I have included my attempt to post token to my server as well. If you do not need the posting mechanism, retain the first 5 lines (til' self.token = dt) in the didRegisterForRemoteNotificationsWithDeviceToken

    ...
    
    @synthesize token;
    
    ...
    
    - (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
    {    
    ...
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
        (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    
        return YES;
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        NSLog(@"Did finish launching with device token %@", deviceToken);
        NSString *dt = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
        dt = [dt stringByReplacingOccurrencesOfString:@" " withString:@""];
    
        self.token = dt;
    
        NSString *dv = [[UIDevice currentDevice] systemVersion];
        NSString *dn = [[UIDevice currentDevice] systemName];
        NSString *nick = [[UIDevice currentDevice] name];
        NSString *model = [[UIDevice currentDevice] model];
        NSString *uniqueIdentifier = [[UIDevice currentDevice] uniqueIdentifier];
    
        NSMutableString *postData = [NSMutableString stringWithString: @"&deviceToken="];
    
        [postData appendString:dt];
        [postData appendFormat:@"&uniqueIdentifier=%@&application_uuid=5ade8400-e29c-41d4-a716-3641972a2ec6", uniqueIdentifier];
        [postData appendFormat:@"&source=ios&name=%@&model=%@&systemName=%@&systemVersion=%@", nick, model, dn, dv];
    
        NSString* escapedURLString = [postData stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
        @try {
            NSData *postData = [escapedURLString dataUsingEncoding:NSUTF8StringEncoding];
            NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
                                            initWithURL: [NSURL URLWithString:@"{YOUR URL TO POST TOKEN TO SERVER}"]
                                            cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval: 180];
            NSString *postLength = [[NSString alloc] initWithFormat: @"%d", [postData length]];
            [request setHTTPMethod:@"POST"];
            [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
            [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            [request setHTTPBody:postData];
    
    
            NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
            if (conn) {
                //??
            }else{
                //??
            }
        }
        @catch (NSException *exception) {
            NSLog(@"Exception %@", exception);
        }
    }
    ...
    

    PushToken.h

    #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
    

    PushToken.m

    #import "PushToken.h"
    #import "AppDelegate.h"
    
    @implementation PushToken
    
    @synthesize callbackID;
    
    - (void)getToken:(NSMutableArray *)arguments withDict:(NSMutableDictionary *)options {
    
        NSLog(@"Did called getToken");
        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
    

    PushToken.js

    var PushToken = {
        /**
        * Get token from the device
        * @param {array} types - By default is ['getToken']
        * @param {function} success Success callback, with token
        * @param {function} fail Failure callback, with null
        */
        getToken: function(types, success, fail) {
            return Cordova.exec(success, fail, "PushToken", "getToken", types);
        },
    
        /**
        * For the sake of iOS, we need an install function
        */
        install: function() {
            window.plugins = window.plugins || {};
            window.plugins.PushToken = PushToken;
        }
    };
    
    /**
    * For the rest of the devices
    */
    window.plugins = window.plugins || {};
    window.plugins.PushToken = PushToken;
    

    Usage

    document.addEventListener('deviceready', function() {
        if (typeof PushToken == 'object') {
            PushToken.install();
        }
    
        PushToken.getToken(['getToken'], function(token) {
            callback(token);
        }, function() {
            callback(null);
        });
    });
    

    And you should be able to get your token from your Javascript side ;)

    Have fun!

    Cheers

    0 讨论(0)
提交回复
热议问题