sdk开发中如何去捕获系统的didReceiveLocalNotification以及didReceiveRemoteNotification通知

50 篇文章 1 订阅
46 篇文章 0 订阅

1. 开发应用程序时, 如果要在接受到本地通知或者远程通知里进行事件处理, 则可以直接在didReceiveLocalNotification和didReceivedRemoteNotification方法中直接进行调用。

应用程序启动时的main.m文件, 直接指定appDelegate

int main(int argc, char * argv[])

{

    @autoreleasepool {

        return UIApplicationMain(argc, argv, nilNSStringFromClass([DemoAppDelegate class]));

    }

}


2. 如果是捕获的是

applicationWillResignActive, 

applicationWillEnterForeground, 

applicationDidBecomeActive, 

didFinishLaunchingWithOptions

根据UIApplication.h中的通知列表中, 表示上述的事件都可以通过通知获取, 通知事件列表如下:

// These notifications are sent out after the equivalent delegate message is called

UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification      NS_AVAILABLE_IOS(4_0);

UIKIT_EXTERN NSString *const UIApplicationWillEnterForegroundNotification     NS_AVAILABLE_IOS(4_0);

UIKIT_EXTERN NSString *const UIApplicationDidFinishLaunchingNotification;

UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification;

UIKIT_EXTERN NSString *const UIApplicationWillResignActiveNotification;

UIKIT_EXTERN NSString *const UIApplicationDidReceiveMemoryWarningNotification;

UIKIT_EXTERN NSString *const UIApplicationWillTerminateNotification;

UIKIT_EXTERN NSString *const UIApplicationSignificantTimeChangeNotification;

UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarOrientationNotification; // userInfo contains NSNumber with new orientation

UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarOrientationNotification;  // userInfo contains NSNumber with old orientation

UIKIT_EXTERN NSString *const UIApplicationStatusBarOrientationUserInfoKey;            // userInfo dictionary key for status bar orientation

UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarFrameNotification;       // userInfo contains NSValue with new frame

UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarFrameNotification;        // userInfo contains NSValue with old frame

UIKIT_EXTERN NSString *const UIApplicationStatusBarFrameUserInfoKey;                  // userInfo dictionary key for status bar frame

UIKIT_EXTERN NSString *const UIApplicationBackgroundRefreshStatusDidChangeNotificationNS_AVAILABLE_IOS(7_0);

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsURLKey                  NS_AVAILABLE_IOS(3_0); // userInfo contains NSURL with launch URL

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsSourceApplicationKey    NS_AVAILABLE_IOS(3_0); // userInfo contains NSString with launch app bundle ID

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsRemoteNotificationKey   NS_AVAILABLE_IOS(3_0); // userInfo contains NSDictionary with payload

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocalNotificationKey    NS_AVAILABLE_IOS(4_0); // userInfo contains a UILocalNotification

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsAnnotationKey           NS_AVAILABLE_IOS(3_2); // userInfo contains object with annotation property list

UIKIT_EXTERN NSString *const UIApplicationProtectedDataWillBecomeUnavailable   NS_AVAILABLE_IOS(4_0);

UIKIT_EXTERN NSString *const UIApplicationProtectedDataDidBecomeAvailable      NS_AVAILABLE_IOS(4_0);

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocationKey             NS_AVAILABLE_IOS(4_0); // app was launched in response to a CoreLocation event.

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsNewsstandDownloadsKey   NS_AVAILABLE_IOS(5_0); // userInfo contains an NSArray of NKAssetDownload identifiers

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsBluetoothCentralsKey    NS_AVAILABLE_IOS(7_0); // userInfo contains an NSArray of CBCentralManager restore identifiers

UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsBluetoothPeripheralsKey NS_AVAILABLE_IOS(7_0); // userInfo contains an NSArray of CBPeripheralManager restore identifiers


3. 对于本地通知调起事件,以及远程通知事件上,你可能会想通过注册上述的通知来进行捕获。 但是, 你在查询了上面这个列表后发现, 没有这两个通知事件。所以你抓狂了, 别急。 下面就是解决这个问题的方法。 开发SDK时,不能像上面第一部分代码中main.m中那样在应用程序启动时能挂上AppDelegate, 所以不能通过appDelgate获取到本地通知和远程通知的调用时机。


3.1分析发现我们可以在程序中获取到

[UIApplication sharedApplication].delegate, 这个delegate默认是指向DemoAppDelegate, 现在我们可以把[UIApplication sharedApplication].delegate指向一个变量proxy, 那么这个变量将会获取到所有原来应用AppDelegate的回调方法, 其中包括appDidFinishLaunchedWithOption, appWillResignActive, appWillEnterForeground等回调用, 同样也包括本地通知以及远程通知调用时的回调。 


等等, 你似乎想到什么。。。


没错, 你这样写会有问题, 会导致原始的appDelegate将会再也获取不到这些回调了, 这是有潜在问题的。 比如你在appDelegate中实现的appWillTerminate中可能会做一些保存数据的操作,上面这样做的话,你的这个appDelegate中的回调就再也调用不了啦, 自然你的数据保存操作也不会被执行。


3.2 紧接着, 你就会想到,有没有什么办法能捕获appDelegate的回调, 但又不影响appDelegate自身的调用呢?


有! 上面这个方法是把这个[UIApplication sharedApplication].delegate指向一个变量proxy, 我们只需要在proxy这个变量中同时把appDelegate也进行调用就可以了。 也即在proxy中,我们可以先处理一下我们想处理的回调方法, 然后继续让这些回调方法继续流转, 如流转到appDelegate即可。也即让自己先处理完成后, 再进行消息的转发。


所以,我们需要如下几个类。

1. 

.h

@interface NABAppDelegate : NSObject <UIApplicationDelegate>

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

@end


.m

#import "NABAppDelegate.h"

@implementation NABAppDelegate

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

{

    NBLog(@"%@, %@", application, notification);

// SDK在这里,可以做自己想做的事

}

@end


2. 

.h

@interface NABAppDelegateProxy : NSProxy <UIApplicationDelegate>

- (id)init;

@property (nonatomicstrongNSObject<UIApplicationDelegate> *naAppDelegate;

@property (nonatomicstrongNSObject<UIApplicationDelegate> *originalAppDelegate;

@end


.m

#import "NABAppDelegateProxy.h"

@implementation NABAppDelegateProxy

- (id)init

{

    return self;

}


- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

{

    NSMethodSignature *sig;

    sig = [self.originalAppDelegate methodSignatureForSelector:aSelector];

    if (sig) {

        return sig;

    } else {

        sig = [self.naAppDelegate methodSignatureForSelector:aSelector];

        return sig;

    }

    return nil;

}


// Invoke the invocation on whichever real object had a signature for it.

- (void)forwardInvocation:(NSInvocation *)invocation

{    

    if ([self naDelegateRespondsToSelector:[invocation selector]]) {

        [invocation invokeWithTarget:self.naAppDelegate];

    }

    

    if ([self.originalAppDelegate methodSignatureForSelector:[invocation selector]]) {

        [invocation invokeWithTarget:self.originalAppDelegate];

    }

}


// Override some of NSProxy's implementations to forward them...

- (BOOL)respondsToSelector:(SEL)aSelector

{    

    if ([self.naAppDelegate respondsToSelector:aSelector])

        return YES;

    if ([self.originalAppDelegate respondsToSelector:aSelector])

        return YES;

    

    return NO;

}


- (BOOL)naDelegateRespondsToSelector:(SEL)selector

{

    return [self.naAppDelegate respondsToSelector:selector] && ![[NSObject classinstancesRespondToSelector:selector];

}

@end



使用时, 只需要在SDK的初始化时, 调用下面代码,前提,SDK的单例类中有一个proxy变量

- (void)addAppDelegateProxy

{

    _proxy = [[NABAppDelegateProxy allocinit];

  

    @synchronized ([UIApplication sharedApplication]) {

        _proxy.naAppDelegate = [[NABAppDelegate allocinit];

        _proxy.originalAppDelegate = [UIApplication sharedApplication].delegate;

        [UIApplication sharedApplication].delegate = _proxy;// 这句最为重要

    }

}


就这样,在SDK中就可以获取到所有原来appDelegate的所有回调用方法了。
接着再分析一下, 

- (BOOL)naDelegateRespondsToSelector:(SEL)selector

{

    return [self.naAppDelegate respondsToSelector:selector] && ![[NSObject class]instancesRespondToSelector:selector];

}

注意一下这个方法中, 最后一句, 有加入[NSObject class]的处理。
这是因为这个方法, 我们是为了取仅仅naDelegate这个变量能处理哪些方法, 排除NSObject能处理的方法外。 因为self.naAppDelegate这个变量是一个NSObject类型, 会有很多NSObject能响应的方法,如isKindOfClass, isEqual等。 这些isKindOfClass, isEqual的方法可以由originalAppDelegate变量去进行响应。 所以用到上述的排除方法。

3.3最后,如果你的代码中需要指定其它的回调对象来接收appDelegate的回调方法, 使用下面方法即可。只要不修改proxy.originalAppDelegate,修改proxy.naAppDelegate即可。

- (void)setCustomAppDelegateProxy:(id<UIApplicationDelegate>)delegate

{

    if (delegate) {

        self.proxy.naAppDelegate = delegate;

    }

}


调用示例:


        NABAppDelegateDemo *demoAppDelegate = [[NABAppDelegateDemo allocinit];

        [[XXXSDK sharedsetCustomAppDelegateProxy:demoAppDelegate];

(注:这里的NABAppDelegateDemo可以是直接继承NABAppDelegate)

@interface NABAppDelegateDemo : NABAppDelegate

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

@end


@implementation NABAppDelegateDemo

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification

{

    NSLog(@"did receive local notification, notification=%@", notification);

    [application cancelLocalNotification:notification]; //(这里可以根据需要决定是否进行cancelNotification)

}


@end


原文:http://blog.csdn.net/smking/article/details/39010067

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是Flutter集成极光推送的步骤: 1. 在极光官网注册账号并创建应用,获取AppKey。 2. 在Flutter项目添加极光推送插件,如:jpush_flutter。 3. 在AndroidManifest.xml文件添加以下代码: ```xml <!-- 极光推送权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 极光推送服务 --> <service android:name="cn.jpush.android.service.PushService" android:enabled="true" android:exported="false" android:process=":pushcore" > <intent-filter> <action android:name="cn.jpush.android.intent.REGISTER" /> <action android:name="cn.jpush.android.intent.REPORT" /> <action android:name="cn.jpush.android.intent.PushService" /> <action android:name="cn.jpush.android.intent.PUSH_TIME" /> </intent-filter> </service> <receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true" android:exported="false" > <intent-filter android:priority="1000"> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED_PROXY" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <data android:scheme="package" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver> ``` 4. 在iOS项目,到极光官网下载JPush SDK并导入到项目,在AppDelegate.m文件添加以下代码: ```objective-c #import "JPUSHService.h" // iOS 10 及以上需导入 UserNotifications.framework #import <UserNotifications/UserNotifications.h> // Override point for customization after application launch. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化 JPush SDK [JPUSHService setupWithOption:launchOptions appKey:@"your_appkey" channel:nil apsForProduction:NO]; return YES; } // 注册APNs成功并上报DeviceToken - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [JPUSHService registerDeviceToken:deviceToken]; } // 实现注册APNs失败接口 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error); } // 添加处理APNs通知回调方法 #ifdef NSFoundationVersionNumber_iOS_9_x_Max // iOS 10之前收到通知 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // Required, iOS 7 Support [JPUSHService handleRemoteNotification:userInfo]; completionHandler(UIBackgroundFetchResultNewData); } // iOS 10之前收到本地通知 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { // Required, iOS 7 Support [JPUSHService showLocalNotificationAtFront:notification identifierKey:nil]; } // iOS 10及以上收到通知 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler { NSDictionary * userInfo = notification.request.content.userInfo; if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; } completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound); } // iOS 10及以上收到本地通知 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { NSDictionary * userInfo = response.notification.request.content.userInfo; if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; } completionHandler(); } #endif ``` 5. 在Flutter代码,初始化JPush并监听推送事件: ```dart import 'package:jpush_flutter/jpush_flutter.dart'; // 初始化JPush JPush jpush = new JPush(); // 监听推送事件 jpush.addEventHandler( onReceiveNotification: (Map<String, dynamic> message) async { print("Flutter onReceiveNotification: $message"); }, onOpenNotification: (Map<String, dynamic> message) async { print("Flutter onOpenNotification: $message"); }, onReceiveMessage: (Map<String, dynamic> message) async { print("Flutter onReceiveMessage: $message"); }, ); // 启动JPush jpush.setup( appKey: "your_appkey", // 极光官网申请的AppKey channel: "developer-default", // 渠道,默认值为“developer-default” production: false, // 是否生产环境 debug: true, // 是否开启调试模式 ); ``` 以上就是Flutter集成极光推送的步骤,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值