推送通知用于Adobe Air的iOS本机扩展

问题描述:

我正在研究Adobe AIR的iOS本机扩展,它将获取推送通知的设备标记。不幸的是,我并不是那种munch objective-C程序员,我不确定在我使用的代码中是否有问题。它编译没有问题,我可以使用AIR的扩展,但看起来像注册通知不会返回正面或负面影响。所以我想要做的是注册通知,当从AIR调用RegisterDevice函数时,如果它注册了将device token存储在deviceTokenString中,并且如果它没有注册并返回错误,我将错误存储在此字符串中。当调用GetToken函数时,我将deviceTokenString返回给AIR,因此它可能是标记或错误。在AIR应用程序中,我通过单击按钮启动第一个RegisterDevice函数以及后来的GetToken函数。不幸的是,我没有得到任何令牌或错误(也弹出询问权限不显示)。我也试图把注册部分放在didFinishLaunchingWithOptions中,但看起来didFinishLaunchingWithOptions从未启动。如果你们可以看看代码是否可以,我会非常感激。或者,也许你有什么想法还有什么可能是错的?我已在配置门户中启用SSL证书。下面的代码我使用推送通知用于Adobe Air的iOS本机扩展

“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 
+0

米哈尔嗨,你一直能够与您的开发成功吗?任何计划发布此ANE? – Eduardo 2012-05-05 09:36:00

的问题是,你不告诉你应用程序,该函数调用,一旦它 已注册与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

所以你基本上是通过指定的头文件和实现创建一个单独的类和设置的这个实例班作为你的应用开发者。现在,您不必要地围绕静态代码包装类,并添加与代理中应该调用的函数具有相同名称的函数,但是不会告诉应用程序关于您的代理。一个好地方,设置您的代理将是你nativeextension,在那里你调用类似的contextinitializer功能:

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

现在的应用程序将调用这种情况下, 的didRegisterForRemoteNotificationsWithDeviceToken方法,一旦你注册的APN。

好吧,

我把头发撕了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; 

}

+1

我们遇到了这个解决方案的问题。另一种实现处理程序的方式是通过NotificationCenter:http://*.com/questions/3639859/handling-applicationdidbecomeactive – Edmundito 2013-12-15 01:59:54