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

Lio*_*han 2 push-notification apple-push-notifications ios cordova

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

方案是,我有这个基于Web的PhoneGap应用程序,本机iOS帮我在APN上注册了设备,我在服务器数据库中收到了设备令牌.

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

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

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

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

Fyi,这个应用程序是为一个活动而构建的,客户已经要求人们在这个移动应用程序上发送消息.当他收到朋友的消息时,如何将新消息通知推送给"John Doe"? - 问题是如何将"John Doe"链接到特定的device_token?

这可能不是iOS特定的,因为此应用程序也必须部署在Android(C2DM)上.

欢迎任何帮助!

编辑:可能解决方案?

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

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

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

编辑:答案

我在答案中公布了完整的工作解决方案.请在此处查看:https://stackoverflow.com/a/9628592/534862

Lio*_*han 5

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

环境

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

工作流程

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

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

AppDelegate.h

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

AppDelegate.m

注意:我是一个Obj-C新手,我也尝试将令牌发布到我的服务器上.如果您不需要发布机制,请保留前5行(直到' self.token = dt)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);
    }
}
...
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

用法

document.addEventListener('deviceready', function() {
    if (typeof PushToken == 'object') {
        PushToken.install();
    }

    PushToken.getToken(['getToken'], function(token) {
        callback(token);
    }, function() {
        callback(null);
    });
});
Run Code Online (Sandbox Code Playgroud)

你应该能够从你的Javascript端获得你的令牌;)

玩得开心!

干杯


cur*_*mil 5

以前的答案是解决这个问题的好方法,他们以非常正式的方式来做.但是,如果您想要快速而肮脏的方法来解决问题,您可以简单地执行此操作:

在didRegisterForRemoteNotificationsWithDeviceToken底部添加

NSString* jsString = [NSString stringWithFormat:@"var deviceToken = \"%@\";", deviceToken];
[self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
Run Code Online (Sandbox Code Playgroud)

在你的JavaScript中

deviceId = (typeof deviceToken !== "undefined") ? deviceToken : null;
Run Code Online (Sandbox Code Playgroud)