前言
推送为远程推送,一般由苹果APNS服务器发送给苹果设备(iPhone,iPad)
推送分在前台和后台。在前台时 用户可以在application 的代理回调接口中做相应处理;在后台时 系统会全权接手所有事宜 所以需要的字端一定要让后端人员配合做好。
{ "aps": { "alert": { "title": "This is .", "body": "who are you" }, "badge": 1, "sound": "default", "category": "Huang_Category", "mutable-content": "1" }, "messageId": 123, "messageType": 0, "userInboxId": "{"2535025486":"123"}", "image": "http://172.16.3.129/pic/1224.jpg" }
客户端发送一个请求给服务端 --> 服务端发送一个请求给APNS --> APNS给特定的设备发送 --> 特定设备的系统收到消息 (在前台 事件传递到app中,这个时候开发者可以操作了,在后台 系统会根据系统设置的通知设置自行处理 )
1. 在配置文件中开启推送权限
2. 在appDelegate的didFinishLaunchingWithOptions 中注册notificationsetting
UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:set]; [application registerUserNotificationSettings:settings]; // set 是一个装载模型为UIMutableUserNotificationCategory的NSSet对象
在回调中注册远程通知
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { [application registerForRemoteNotifications]; }
此时苹果服务器会返回一个devicetoken给我们,这个devicetoken一般是不会变的
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{ NSLog(@"deviceToken %@",deviceToken); } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{ NSLog(@"error %@",error); }
3. 本地推送
3.1 发送本地通知
- (void)showLocalNotificationWithUserInfo:(NSDictionary *)userInfo fireDate:(NSDate *)firDate{ NSDictionary * aps = [userInfo objectForKey:@"aps"]; NSString * body; NSDictionary * alert = [aps objectForKey:@"alert"]; if ([alert isKindOfClass:[NSString class]]) { body = (NSString *)alert; }else{ body = [alert objectForKey:@"body"]; } UILocalNotification * notification = [[UILocalNotification alloc] init]; NSDictionary * hgl = @{ @"huang":@5, @"gu":@(2), @"long":@"4" }; NSMutableDictionary * newInfo = [NSMutableDictionary dictionaryWithDictionary:userInfo]; [newInfo setObject:hgl forKey:@"hgl"]; notification.userInfo = newInfo; notification.fireDate = firDate; notification.alertBody = body; notification.category = [aps objectForKey:@"category"]; if (@available(iOS 8.2, *)) { notification.alertTitle = [alert objectForKey:@"title"]; } else { // Fallback on earlier versions } notification.applicationIconBadgeNumber = 1; if ([UIApplication sharedApplication].currentUserNotificationSettings.types & UIUserNotificationTypeSound) { notification.soundName = UILocalNotificationDefaultSoundName; if (notification.fireDate.timeIntervalSinceNow <= 1) { if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { AudioServicesPlaySystemSound(1007); /* NSArray * array = @[@(1002),@(1007),@(1011),@(1012),@(1015),@(1050),@(1055)]; static int m = 0;//02,07,11,12,15,50,55, NSNumber * n = array[m%7]; AudioServicesPlaySystemSound(n.integerValue); NSLog(@"------%ld",n.integerValue); m++; */ } } } //生效时间根据fireDate确定 [[UIApplication sharedApplication] scheduleLocalNotification:notification]; //立即生效的通知,与fireDate无关 // [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; }
3.2 前台
发送本地推送后,此时会回调 didReceiveLocalNotification的方法,并不会弹框 ,但是会在通知中心留有一个推送信息
在通知中心点击通知后 也会回调didReceiveLocalNotification
后台
一般用延时操作可以达到后台效果,此时会系统接收做处理
点击通知后 也会回调didReceiveLocalNotification 不过此时application.applicationState的为 UIApplicationStateInactive
4. 远程
使用一些网上的工具可以给指定的设备 发送远程推送
eg. SmartPush
前台
收到推送时 didReceiveLocalNotification会回调,这时你可以做自己想要做的事啦 (一般无法就是再发一个本地推送,这时又回调 3啦)
点击通知后 会回调didReceiveLocalNotification
后台
系统会帮忙处理的 是否弹框
点击通知后 didReceiveLocalNotification会回调
离线
系统会帮忙处理的 是否弹框
点击通知后 didReceiveLocalNotification会回调
------------------------------------------------------------------------------------------------
注 :
注册的时候 我们生成 UIUserNotificationSettings对象时 用到了一个set ,这个set一般我会用nil代替,他的左右是在通知右滑的时候显示按钮用的 (至多2个)
UIMutableUserNotificationAction * joinAction = [[UIMutableUserNotificationAction alloc] init]; joinAction.title = @"接受交友"; joinAction.authenticationRequired = YES; joinAction.identifier = @"gu.join"; UIMutableUserNotificationAction * lookAction = [[UIMutableUserNotificationAction alloc] init]; lookAction.title = @"查看信息"; lookAction.identifier = @"gu.look"; lookAction.activationMode = UIUserNotificationActivationModeForeground; UIMutableUserNotificationAction * cancelAction = [[UIMutableUserNotificationAction alloc] init]; cancelAction.title = @"取消"; cancelAction.identifier = @"gu.cancel"; cancelAction.destructive = YES; UIMutableUserNotificationCategory * noticeCategory = [[UIMutableUserNotificationCategory alloc] init]; noticeCategory.identifier = @"Huang_Category"; [noticeCategory setActions:@[joinAction,lookAction] forContext:(UIUserNotificationActionContextDefault)]; NSMutableSet * set = [NSMutableSet setWithObject:noticeCategory]; if (@available(iOS 9.0, *)) { UIMutableUserNotificationAction * inputAction = [[UIMutableUserNotificationAction alloc] init]; inputAction.title = @"评论"; inputAction.identifier = @"gu.input"; inputAction.behavior = UIUserNotificationActionBehaviorTextInput; inputAction.parameters = @{ UIUserNotificationTextInputActionButtonTitleKey:@"我说" }; UIMutableUserNotificationCategory * inputCategory = [[UIMutableUserNotificationCategory alloc] init]; inputCategory.identifier = @"Long_Category"; [inputCategory setActions:@[inputAction] forContext:(UIUserNotificationActionContextDefault)]; [set addObject:inputCategory]; }
点击通知上的按钮后 根据远程和本地 8.0/9.0 会有四个不同方法的回调
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler{ [self gl_handleActionWithIdentifier:identifier userInfo:notification.userInfo withResponseInfo:nil]; NSLog(@"%s",__FUNCTION__); completionHandler(); } - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler{ [self gl_handleActionWithIdentifier:identifier userInfo:userInfo withResponseInfo:nil]; NSLog(@"%s",__FUNCTION__); completionHandler(); } - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler{ [self gl_handleActionWithIdentifier:identifier userInfo:notification.userInfo withResponseInfo:responseInfo]; NSLog(@"%s",__FUNCTION__); completionHandler(); } - (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler{ [self gl_handleActionWithIdentifier:identifier userInfo:userInfo withResponseInfo:responseInfo]; NSLog(@"%s",__FUNCTION__); completionHandler(); }