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



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

场景是,我有这个基于PhoneGap网络的应用程序,本地iOS帮助我在APN上注册设备,我在服务器数据库中收到了设备令牌。

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

  • 我现在想的是编写一个自定义插件,并在用户注册期间传递设备令牌。还有更好的选择吗

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

  • 也许每当用户登录时,我都会做一个window.plugins.PluginName.getDeviceToken并同步它
  • {user_id:123, old_device_token: 'xxxx..', new_device_token: 'xxx...'}

Fyi,这个应用程序是为一个事件而构建的,客户端已经在这个移动应用程序上请求了人与人之间的消息。当"John Doe"收到朋友的消息时,你如何向他推送新消息通知?-问题是如何将"John Doe"链接到特定的设备_token?

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

欢迎任何帮助!

编辑:可能的解决方案

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

  1. [本机]应用程序已启动-APN注册已启动,收到device_token
  2. [本机]将此device_token存储到本地存储(CoreData/SqlLite或Property Lists?)中,并将其发送到服务器以进行device_toke注册
  3. [WebView]每当用户登录或注册时,都会通过PhoneGap查询此设备_token,对其进行哈希处理并发送到服务器以进行登录、比较和链接

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

编辑:回答

我的完整工作解决方案张贴在答复中。点击此处查看:https://stackoverflow.com/a/9628592/534862

为了完整起见,这是我使用@TDeBailleul解决方案后的解决方案。转到科尔多瓦。(仅在iOS上测试。在我完成Android版本后,我将发布一个插件:

环境

  • Cordova 1.5.0(以前的PhoneGap)
  • Xcode 4.3.1
  • iOS 5.1
  • Mac OS X 10.7.3
  • 不要使用自动参考计数(ARC)以避免编译错误
  • 通过这个超长的教程,准备好你的推送通知证书

工作流程

  1. [本机]应用程序已启动-APN注册已启动,并且在服务器端接收到device_token
  2. [本机]应用程序将令牌存储在AppDelegate中,要获取令牌,请使用以下代码中的PushToken
  3. [WebView]每当用户登录或注册时,令牌都会通过Cordova(前身为PhoneGap)插件调用,进行哈希处理,然后发送到服务器进行登录、匹配并将用户链接到特定设备

下面是我的完整工作代码,用于进行令牌的本地提取。服务器部分只是将帐户链接到设备。你应该知道如何通过你最喜欢的服务器端应用程序来实现它。

AppDelegate.h

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

AppDelegate.m

注意:我是一个Obj-C新手,我也尝试将令牌发布到我的服务器。如果您不需要过帐机制,请在didRegisterForRemoteNotificationsWithDeviceToken中保留前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;

好吧,我终于制作了一个插件,它似乎可以工作

1-确保您的PhoneGap Xcode项目已针对iOS 4 SDK进行了更新。

2-在插件文件夹中创建一个PushToken文件夹,添加以下PushToken.m和PushTokon.h文件,然后使用"为任何添加的文件夹创建组"将文件夹拖动到XCode中的插件文件夹

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

4-在PhoneGap.plist 的插件中添加带有密钥PushToken和字符串值PushToken的新条目

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 : rn"+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 上成功了

希望这能帮助

最新更新