3

プッシュ通知用のデバイス トークンを取得する Adob​​e AIR の iOS ネイティブ拡張に取り組んでいます。残念ながら、私は客観的な C プログラマーではないので、使用しているコードに何か問題があるかどうかはわかりません。問題なくコンパイルされます。拡張機能をAIRで使用できますが、通知に登録してもプラスの効果もマイナスの効果も返されないようです。したがって、私がやろうとしているのは、RegisterDevice 関数が AIR から呼び出されたときに通知を登録することです。登録されている場合は、デバイス トークンを deviceTokenString に格納し、登録されずにエラーが返された場合は、この文字列にエラーを格納します。 . GetToken 関数が呼び出されると、deviceTokenString を AIR に返すので、トークンまたはエラーのいずれかになります。AIR アプリケーションでは、最初に RegisterDevice 関数を起動し、その後ボタンをクリックして GetToken 関数を起動します。残念ながら、トークンもエラーも表示されません (許可を求めるポップアップも表示されません)。また、didFinishLaunchingWithOptions に登録部分を入れようとしましたが、didFinishLaunchingWithOptions が起動されないようです。コードに問題がなければご覧いただければ幸いです。それとも、他に何が間違っている可能性があるか考えていますか? プロビジョニング ポータルでプッシュ SSL 証明書を有効にしました。これが私が使用しているコードです コードに問題がなければご覧いただければ幸いです。それとも、他に何が間違っている可能性があるか考えていますか? プロビジョニング ポータルでプッシュ SSL 証明書を有効にしました。これが私が使用しているコードです コードに問題がなければご覧いただければ幸いです。それとも、他に何が間違っている可能性があるか考えていますか? プロビジョニング ポータルでプッシュ 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
4

2 に答える 2

4

Ok、

3日間髪を引き裂いた後、私はそれを理解しました. アドビのすべてのものを壊すので、デリゲートを設定しません。既存のデリゲートのカスタム サブクラスを作成し、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;

}

于 2012-02-29T12:51:11.700 に答える
2

問題は、アプリケーションが apns に登録された後、どの関数を呼び出すかをアプリケーションに指示しないことです。そのためには、いわゆるデリゲートを作成して設定する必要があります。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 として設定します。現在、クラスを静的コードに不必要にラップし、デリゲートで呼び出す必要がある関数と同じ名前の関数を追加していますが、デリゲートについてアプリケーションに通知していません。デリゲートを設定するのに適した場所は、nativeextension の contextinitializer 関数で、次のように呼び出します。

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

apns に登録すると、アプリケーションはこのインスタンスの didRegisterForRemoteNotificationsWithDeviceToken メソッドを呼び出します。

于 2012-02-09T12:48:43.070 に答える