Предложение о том, как связать токен устройства APN с зарегистрированным пользователем (через phonegap или UIWebView) - PullRequest
2 голосов
/ 23 февраля 2012

Аналогичный вопрос здесь: jQueryMobile, Phonegap и Device Token - iOS

Сценарий таков: у меня есть это веб-приложение PhoneGap, а родная iOS помогает мне зарегистрировать устройство в APNи я получил токен устройства в своей базе данных сервера.

Вопрос 1: Как связать зарегистрированного пользователя (через UIWebView) с этим токеном устройства с помощью PhoneGap?

  • Теперь я думаю о том, чтобы написать собственный плагин и передать маркер устройства во время регистрации пользователя.Есть ли лучшая альтернатива?

Вопрос 2: Поскольку device_token можно время от времени менять, как я должен повторно связать этого пользователя с этим device_token?

  • Возможно, когда пользователь входит в систему, я делаю window.plugins. PluginName .getDeviceToken и синхронизирую его?
  • {user_id:123, old_device_token: 'xxxx..', new_device_token: 'xxx...'}?

К вашему сведению, это приложение предназначено для проведения мероприятий, и клиент запросил людей для обмена сообщениями в этом мобильном приложении.Как вы отправляете уведомление о новом сообщении Джону Доу, когда он получил сообщение от своего друга?- Вопрос в том, как связать «Джон Доу» с определенным токеном устройства?

Это не может быть слишком специфично для iOS, так как это приложение должно быть развернуто и на Android (C2DM).

Любойпомощь приветствуется!

Редактировать: Возможное решение?

Неустанные исследования выявляют это возможное решение:

  1. [Собственное] Приложение запущено - регистрация APN запущена и device_token
  2. [Собственный] Сохраните этот device_token в локальном хранилище (CoreData / SqlLite или Списки свойств?) и отправьте его на сервер для регистрации device_token
  3. [WebView] Всякий раз, когда пользователь входит в систему илирегистрация, этот device_token будет запрашиваться через PhoneGap, хэшироваться и отправляться на сервер для выполнения входа, сравнения и соединения.

Любой непредвиденный сценарий проблематичен?

РЕДАКТИРОВАТЬ: Ответ

В моем ответе опубликовано мое полное рабочее решение.Проверьте это здесь: https://stackoverflow.com/a/9628592/534862

Ответы [ 3 ]

5 голосов
/ 09 марта 2012

Ради полноты, это мое решение после использования решения @TDeBailleul. Портирован на Кордову. (Проверено только на iOS. После того, как я закончу версию Android, я опубликую плагин для этого:

Окружающая среда

  • Cordova 1.5.0 (ранее PhoneGap)
  • Xcode 4.3.1
  • iOS 5.1
  • Mac OS X 10.7.3
  • Не использовать автоматический подсчет ссылок (ARC), чтобы избежать ошибки компиляции
  • Пройдите это чертовски длинное учебное пособие , чтобы подготовить свой сертификат push-уведомлений

Рабочий поток

  1. [Собственное] Приложение запущено - регистрация 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;

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

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

Веселись!

Приветствия

5 голосов
/ 03 июня 2012

Предыдущие ответы - действительно отличные способы решить эту проблему, и они делают это очень формально. Однако, если вам нужен быстрый и грязный метод решения проблемы, вы можете просто сделать это:

внизу didRegisterForRemoteNotificationsWithDeviceToken add

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

В вашем javascript

deviceId = (typeof deviceToken !== "undefined") ? deviceToken : null;
3 голосов
/ 27 февраля 2012

Хорошо, я наконец-то сделал плагин, который, кажется, работает

1 - убедитесь, что ваш проект PhoneGap Xcode обновлен для iOS 4 SDK.

2 - создайте папку PushToken в папке плагинов, добавьте в нее следующие файлы PushToken.m и PushToken.h, а затем перетащите папку в папку плагинов в XCode, используя «Создать группы для любых добавленных папок»

3 - Добавьте файлы PushToken.js в папку www на диске и добавьте ссылки на файлы .js в виде тегов в свои файлы html

4 - Добавить новую запись с ключом PushToken и строковым значением 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

Надеюсь, это поможет

...