родное расширение для push-уведомлений для Adobe Air - PullRequest
3 голосов
/ 09 февраля 2012

Я работаю над собственным расширением iOS для Adobe AIR, которое получит маркер устройства для push-уведомлений. К сожалению, я не такой программист на munch target-C и не уверен, что что-то не так в коде, который я использую. Компилируется без проблем, я могу использовать расширение с AIR, но похоже, что регистрация уведомлений не дает ни положительного, ни отрицательного эффекта. Итак, что я пытаюсь сделать, это зарегистрироваться для уведомлений, когда функция RegisterDevice вызывается из AIR, и если она регистрируется, сохраните токен устройства в deviceTokenString, и если он не регистрируется и возвращается с ошибкой, я сохраняю ошибку в этой строке , Когда вызывается функция GetToken, я возвращаю deviceTokenString в AIR, так что это либо токен, либо ошибка. В приложении AIR я запускаю первую функцию RegisterDevice, а затем функцию GetToken, нажимая кнопки. К сожалению, я не получаю ни токена, ни ошибки (также не появляется всплывающее окно с запросом разрешения). Я также пытался поместить регистрирующую часть в didFinishLaunchingWithOptions, но похоже, что didFinishLaunchingWithOptions никогда не запускался. Если вы, ребята, можете посмотреть, в порядке ли код, я был бы очень благодарен. Или, может быть, у вас есть идеи, что еще может быть не так? Я включил сертификат SSL в портале инициализации. Вот код, который я использую

"NativePush.m":

#import "UIKit/UIKit.h"
#import "include/FlashRuntimeExtensions.h"

@implementation NativePush

@synthesize tokenString = _tokenString;

NSString *deviceTokenString = @"";

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {       
    return YES;
}

- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken 
{ 
    NSString *str = 
    [NSString stringWithFormat:@"%@",deviceToken];
    deviceTokenString = str;
}

- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err 
{ 
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];   
    deviceTokenString = str;
}

void ContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx,
                        uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet) {
    *numFunctionsToTest = 2;
    FRENamedFunction* func = (FRENamedFunction*)malloc(sizeof(FRENamedFunction)*2);
    func[0].name = (const uint8_t*)"RegisterDevice";
    func[0].functionData = NULL;
    func[0].function = &RegisterDevice;

    func[1].name = (const uint8_t*)"GetToken";
    func[1].functionData = NULL;
    func[1].function = &GetToken;

    *functionsToSet = func;
}

void ContextFinalizer(FREContext ctx) {
    return;
}

void ExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet,
                    FREContextFinalizer* ctxFinalizerToSet) {
    *extDataToSet = NULL;
    *ctxInitializerToSet = &ContextInitializer;
    *ctxFinalizerToSet = &ContextFinalizer;
}

void ExtFinalizer(void* extData) {
    return;
}

FREObject RegisterDevice(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {

    [[UIApplication sharedApplication] 
     registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeAlert | 
      UIRemoteNotificationTypeBadge | 
      UIRemoteNotificationTypeSound)];

    return NULL;
}

FREObject GetToken(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {

    NSString* tokenS =  deviceTokenString;

    char* tokenChar = [tokenS UTF8String];
    FREObject tokenObject = NULL;

    FRENewObjectFromUTF8( strlen(tokenChar)+1 , (const uint8_t*)tokenChar, &tokenObject);

    return tokenObject;

}

@end

и заголовочный файл "NativePush.h":

import "Foundation/Foundation.h"
import "include/FlashRuntimeExtensions.h"

@interface NativePush : NSObject
@property (nonatomic, retain) NSString* tokenString;

FREObject RegisterDevice(
                        FREContext ctx,
                        void* funcData,
                        uint32_t argc,
                        FREObject arg[]
                        );
FREObject GetToken(
                        FREContext ctx,
                        void* funcData,
                        uint32_t argc,
                        FREObject arg[]
                        );
void ContextInitializer(
                        void* extData,
                        const uint8_t* ctxType,
                        FREContext ctx,
                        uint32_t* numFunctionsToTest,
                        const FRENamedFunction** functionsToSet
                        );
void ContextFinalizer(FREContext ctx);
void ExtInitializer(
                    void** extDataToSet,
                    FREContextInitializer* ctxInitializerToSet,
                    FREContextFinalizer* ctxFinalizerToSet
                    );
void ExtFinalizer(void* extData);
@end

Ответы [ 2 ]

4 голосов
/ 29 февраля 2012

Хорошо,

После того, как вырвал мои волосы в течение 3 дней, я понял это.Я не назначаю делегата, потому что это сломает все вещи Adobe.Я создаю пользовательский подкласс существующего делегата и переопределяю функции делегата, которые имеют отношение к APNS.Мой код ниже.

//empty delegate functions, stubbed signature is so we can find this method in the delegate
//and override it with our custom implementation
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken{}

    - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error{}


   //custom implementations of empty signatures above
void didRegisterForRemoteNotificationsWithDeviceToken(id self, SEL _cmd, UIApplication* application, NSData* deviceToken)
{
NSLog(@"My token is: %@", deviceToken);
}


 void didFailToRegisterForRemoteNotificationsWithError(id self, SEL _cmd, UIApplication* application, NSError* error)
{
NSLog(@"Failed to get token, error: %@", error);
}





// ContextInitializer()
//
// The context initializer is called when the runtime creates the extension context instance.
void PushContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, 
                    uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet) 
{

//injects our modified delegate functions into the sharedApplication delegate

id delegate = [[UIApplication sharedApplication] delegate];

Class objectClass = object_getClass(delegate);

NSString *newClassName = [NSString stringWithFormat:@"Custom_%@", NSStringFromClass(objectClass)];
Class modDelegate = NSClassFromString(newClassName);
if (modDelegate == nil) {
    // this class doesn't exist; create it
    // allocate a new class
    modDelegate = objc_allocateClassPair(objectClass, [newClassName UTF8String], 0);

    SEL selectorToOverride1 = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:);

    SEL selectorToOverride2 = @selector(application:didFailToRegisterForRemoteNotificationsWithError:);

    // get the info on the method we're going to override
    Method m1 = class_getInstanceMethod([jreporterNativePush class], selectorToOverride1);
    Method m2 = class_getInstanceMethod([jreporterNativePush class], selectorToOverride2);

    // add the method to the new class
    class_addMethod(modDelegate, selectorToOverride1, (IMP)didRegisterForRemoteNotificationsWithDeviceToken, method_getTypeEncoding(m1));

    class_addMethod(modDelegate, selectorToOverride2, (IMP)didFailToRegisterForRemoteNotificationsWithError, method_getTypeEncoding(m2));

    // register the new class with the runtime
    objc_registerClassPair(modDelegate);
}
// change the class of the object
object_setClass(delegate, modDelegate);


NSLog(@"completed crazy swap w/o bombing  w00t");

///////// end of delegate injection / modification code



*numFunctionsToTest = 1;

FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * 1);

func[0].name = (const uint8_t*) "registerPush";
func[0].functionData = NULL;
func[0].function = &registerPush;

*functionsToSet = func;

}

2 голосов
/ 09 февраля 2012

проблема в том, что вы не сообщаете приложению, какую функцию вызывать, после того как оно зарегистрировано в apns.для этого вам необходимо создать и установить так называемый делегат - прочитайте https://developer.apple.com/library/ios/#documentation/General/Concept ual / CocoaEncyclopedia / DelegatesandDataSources / DelegatesandDataSources.html # // apple_ref / doc / uid / TP40010810-CH11-SW1

вы создаете необходимый делегат путем реализации протокола UIApplicationDelegate.протокол очень похож на концепцию интерфейсов в java - читайте https://developer.apple.com/library/ios/#referencelibrary/GettingStart ed / Learning_Objective-C_A_Primer / _index.html

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

delegate = [[UINativePushAppDelegate alloc] init];
[[UIApplication sharedApplication] setDelegate:delegate];  // assuming there is a class, called uinativepushappdelegate

, теперь приложение будет вызывать метод didRegisterForRemoteNotificationsWithDeviceToken этого экземпляра, как только вы зарегистрируетесь для apns.

...