iOS知识点

iOS APNs推送机制

2020-08-14  本文已影响0人  Cherry_06

APNs简介
Apple Push Notification service(APNs),即苹果推送通知服务。注:这里指的是远程推送通知,不包括本地通知。

为什么会有APNs
移动设备内存、CPU、电量的局限性,iOS不允许app的进程常驻后台(申请特殊权限除外)。
当用户主动杀掉app或者app进入后台超过限定时长时,就意味着app进程的结束。这很大程序保障了前台app的流畅性,也处长了手机的使用时长,这也是苹果用户体验好的原因之一。但也意味着服务器无法主动和用户交互了,比如推送实时消息。为了解决这个限制,苹果推出了APNs,允许设备和服务器分别与苹果的推送通知服务器保持长连接状态。

准备工作
在苹果后台给对应的App ID开通Push Notifications权限,生成profile(用于真机测试),生成APNs证书(用于服务端),

推送流程

APNs推送机制 APNs详细工作流程

iOS代码

注册推送:
首先引入UserNotifications.framework,引入头文件

#import <UserNotifications/UserNotifications.h>
  1. 在didFinishLaunchingWithOptions方法中注册通知:
    if (@available(iOS 10.0, *)) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self;
        [center requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge completionHandler:^(BOOL granted, NSError *_Nullable error) {
            if (granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                                   [[UIApplication sharedApplication] registerForRemoteNotifications];
                               });
            } else {
                NSLog(@"APNs注册失败");
            }
        }];
    } else if (@available(iOS 8.0, *)) {
        UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
        UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
        //register for deviceToken
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
  1. 获取deviceToken
    一般来说会将获取到的deviceToken发送给后台,用于指定设备发送通知。
//注册成功
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    NSString *deviceTokenStr = [[[[deviceToken description]
    stringByReplacingOccurrencesOfString:@"<" withString:@""]
    stringByReplacingOccurrencesOfString:@">" withString:@""]
    stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"deviceTokenStr:\n%@",deviceTokenStr);
}
//注册失败
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"error -- %@",error);
}

注意,如果注册失败,先检查证书是否配置正确,工程是否打开了push开关。另外,app只有在第一次安装时才会弹出系统权限提示。如果没有弹出,可以把app删除,重新build运行一次。

3.处理推送过来的消息
iOS10及以上:

//在前台是否展示
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler{
      // 这个方法表明应用在前台也会通知声音、角标和提示
      completionHandler(UNNotificationPresentationOptionBadge|
      UNNotificationPresentationOptionSound|
      UNNotificationPresentationOptionAlert);
}
//点击收到的消息,会触发下面方法,处理收到的数据
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler{
    //  [self handlePushMessage:response.notification.request.content.userInfo];
      completionHandler();       
}

iOS8以上iOS10以下:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary * _Nonnull)userInfo fetchCompletionHandler:(void (^ _Nonnull)(UIBackgroundFetchResult))completionHandler{
      NSLog(@"didReceiveRemoteNotification:%@",userInfo);
      /* 
       UIApplicationStateActive 应用程序处于前台
      UIApplicationStateBackground 应用程序在后台,用户从通知中心点击消息将程序从后台    调至前台
      UIApplicationStateInactive 用用程序处于关闭状态(不在前台也不在后台),用户通过点击通知中心的消息将客户端从关闭状态调至前台
      */
      //应用程序在前台给一个提示特别消息
      if (application.applicationState == UIApplicationStateActive) {
            //应用程序在前台
            [self createAlertViewControllerWithPushDict:userInfo];
      }else{
            //其他两种情况,一种在后台程序没有被杀死,另一种是在程序已经杀死。用户点击推送的消息进入app的情况处理。
              [self handlePushMessage:userInfo];
      }
      completionHandler(UIBackgroundFetchResultNewData);
}

后台还未开发,或者收不到推送,如何测试iOS代码和证书有无问题?
我都是用Pusher这个软件,导入.p12证书,填入deviceToken就可以测试发送了。
后台的证书是.pem格式,可通过命令将.p12文件转为.pem文件:

openssl pkcs12 -in origin.p12 -out dis.pem -nodes
上一篇 下一篇

猜你喜欢

热点阅读