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

发布于 2025-01-03 11:28:03 字数 4359 浏览 0 评论 0原文

我正在为 Adob​​e AIR 开发 iOS 本机扩展,它将获取推送通知的设备令牌。不幸的是,我不是那么热心的 Objective-C 程序员,我不确定我正在使用的代码是否有问题。它编译没有问题,我可以将扩展与 AIR 一起使用,但看起来注册通知不会返回正面或负面效果。所以我想做的是,当从 AIR 调用 RegisterDevice 函数时注册通知,如果它确实注册,则将设备令牌存储在 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

I'm working on iOS native extension for Adobe AIR that will get device token for push notifications. Unfortunately I'm not that munch objective-C programmer and I'm not sure if there's something wrong in the code I'm using. It compiles with no problem, I can use the extension with AIR but looks like registering for notifications doesn't return neither positive nor negative effect. So what I'm trying to do is register for notifications when RegisterDevice function is called from AIR and if it does register store the device token in deviceTokenString and if it doesn't register and comes back with the error I store the error in this string. When GetToken function is called I return deviceTokenString to AIR so it's either token or error. In AIR application I launch first RegisterDevice function and later GetToken function by clicking buttons. Unfortunately I don't get neither token nor error (also popup asking for permission doesn't show up). I was also trying to put registering part in didFinishLaunchingWithOptions but it looks like didFinishLaunchingWithOptions is never launched. If you guys can have a look if the code is OK I would be really grateful. Or maybe you have any ideas what else can be wrong? I have push SSL certificate enabled in provisioning portal. Here's the code I'm using

"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

and header file "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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷默言语 2025-01-10 11:28:03

好吧,

在撕扯我的头发三天后,我想通了。我不设置委托,因为这会破坏 Adob​​e 的所有东西。我创建现有委托的自定义子类并覆盖与 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 = ®isterPush;

*functionsToSet = func;

}

Ok,

After tearing my hair out for 3 days I figured it out. I dont set the delegate, because that will break all Adobe's stuff. I create a custom subclass of the existing delegate and override the delegate functions that have to do with APNS. My code is below.

//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 = ®isterPush;

*functionsToSet = func;

}

白衬杉格子梦 2025-01-10 11:28:03

问题是,一旦应用程序调用它,您就不会告诉它要调用哪个函数
已向 apns 注册。为此,您必须创建并设置一个所谓的
委托 - 阅读 https://developer.apple.com/library/ios/#文档/常规/概念 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

因此您基本上将通过指定头文件和实现来创建一个单独的类并将此类的实例设置为您的 uiapplicationdelegate。现在,您不必将类包装在静态代码周围,并添加与应在委托中调用的函数同名的函数,但您不告诉应用程序有关您的委托的信息。设置委托的一个好地方是您的 nativeextension 的 contextinitializer 函数,您可以在其中调用类似的内容:

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

现在应用程序将调用此实例的 didRegisterForRemoteNotificationsWithDeviceToken 方法,
一旦你注册了 apns。

the problem is, that you do not tell your application, which function to call, once it
has registered with apns. in order to do that, you have to create and set a so-called
delegate - read https://developer.apple.com/library/ios/#documentation/General/Concept ual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources. html#//apple_ref/doc/uid/TP40010810-CH11-SW1

you create the needed delegate by implementing the UIApplicationDelegate protocol.
a protocol is quite similar to the concept of interfaces in java - read https://developer.apple.com/library/ios/#referencelibrary/GettingStart ed/Learning_Objective-C_A_Primer/_index.html

so you will basically create a SEPARATE class by specifying a header file and implementation and set an instance of this class as your uiapplicationdelegate. right now, you unnecessarily wrap a class around static code and add functions that have the same name as functions that should be called in the delegate, but you do not tell the application about your delegate. a good place to set your delegate would be the contextinitializer function of your nativeextension, where you call something like:

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

now the application will call the didRegisterForRemoteNotificationsWithDeviceToken method of this instance,
once you register for apns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文