build议如何将APN的设备令牌链接到注册用户(通过phonegap或UIWebView)

类似的问题在这里: jQueryMobile,Phonegap和设备令牌 – iOS

情况是,我有这个PhoneGap基于Web的应用程序,并且本地iOS帮助我在APN上注册设备,并且在我的服务器数据库中收到设备令牌。

问题1:如何使用PhoneGap将注册用户(通过UIWebView)关联到此设备令牌?

  • 现在我想到的是编写自定义插件,并在用户注册期间传递设备令牌。 有没有更好的select?

问题2:由于device_token可以随时更改,我应该如何将这个用户重新链接到这个device_token?

  • 也许每当用户login,我做一个window.plugins。 PluginName .getDeviceToken并同步它?
  • {user_id:123, old_device_token: 'xxxx..', new_device_token: 'xxx...'}

Fyi,这个应用程序是为一个事件而构build的,客户请求人们在这个移动应用程序上发送消息。 当他收到他的朋友发来的消息时,你如何向“John Doe”推送新消息通知 ? – 问题是如何将“John Doe”链接到特定的device_token?

这不能太iOS专用,因为这个应用程序也必须在Android上部署(C2DM)。

欢迎任何帮助!

编辑:可能的解决办法

不安的研究出现了这个可能的解决scheme:

  1. [Native]应用程序已启动 – 已启动APN注册,并收到device_token
  2. [Native]将此device_token存储到本地存储(CoreData / SqlLite或Property Lists?)中,并将其发送到服务器以执行device_token注册
  3. [WebView]每当用户login或注册,这个device_token将通过PhoneGap查询,散列并发送到服务器进行login,比较和链接。

任何不可预见的情况都是有问题的?

编辑:答案

我有我的完整工作解决scheme张贴在答案。 看看这里: https : //stackoverflow.com/a/9628592/534862

好的,我终于做了一个似乎工作的插件

1 – 确保您的PhoneGap Xcode项目已经更新为iOS 4 SDK。

2 – 在插件文件夹中创build一个PushToken文件夹,将下面的PushToken.m和PushToken.h文件添加到它,然后将该文件夹拖到XCode中的插件文件夹,使用“为所有添加的文件夹创build组”

3 – 将PushToken.js文件添加到磁盘上的www文件夹中,并将引用添加到.js文件中,作为html文件中的标记。

4 – 用键PushToken和string值PushToken添加到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); } }; 

如何使用

 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); } 

我使它在PhoneGap 1.1上工作

希望这可以帮助

为了完整起见,这是我使用@TDeBailleul解决scheme后的解决scheme。 移植到cordova。 (仅在iOS上testing完成后,我会发布一个插件:

环境

  • cordova1.5.0(原名PhoneGap)
  • Xcode 4.3.1
  • iOS 5.1
  • Mac OS X 10.7.3
  • 不要使用自动引用计数(ARC)来避免编译错误
  • 通过这个令人毛骨悚然的漫长的教程来准备好您的推送通知证书

工作stream程

  1. [Native]应用程序已启动 – 已启动APN注册,并在服务器端收到device_token
  2. [Native] Application将令牌存储在AppDelegate ,并获取令牌,使用以下代码中的PushToken
  3. [WebView]当用户login或注册时,令牌将通过Cordova(以前称为PhoneGap)插件调用,散列并发送到服务器进行login,将用户匹配并链接到特定设备。

所以下面是我完成的工作代码,做本机拉动的令牌。 服务器部分不过是将帐户链接到设备。 你应该知道如何通过你最喜欢的服务器端应用程序来完成它。

AppDelegate.h

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

AppDelegate.m

注意:我是一个Obj-C的新手,我也包括了将令牌发布到我的服务器的尝试。 如果您不需要发布机制,请在self.token = dt保留前5行(直到“ self.token = dt

 ... @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; 

用法

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

而且你应该能够从你的Javascript端获得你的代币;)

玩的开心!

干杯

以前的答案是解决这个问题的非常好的方法,他们以非常正式的方式做到这一点。 但是,如果你想要一个快速和肮脏的方法来解决这个问题,你可以简单地这样做:

在didRegisterForRemoteNotificationsWithDeviceToken的底部添加

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

在你的JavaScript

 deviceId = (typeof deviceToken !== "undefined") ? deviceToken : null;