iOS-简单集成APNS推送

本篇文章对APNS推送进行几点总结:

  • 1.ANPS 原理是什么?
  • 2.工程如何集成APNS推送
  • 3.项目中遇到的坑

一.ANPS 原理

1.App 在代码中注册消息推送弹框 ;
2.iOS从ANPS服务器获取Device Token,回传给APP
3.APPDevice Token 发送给自己公司服务器
4.APP 发消息到自己公司服务器后,自己公司服务器将要发送的消息,目的iPhone的标识打包发送给ANPS服务器;
5.ANPS服务器在自身的已注册Push服务的设备列表中,查找有相应标识的设备,并把消息发送到设备的APP,并且按照设定弹出Push通知。
具体原理图看下图解释:

APNS原理图.png

二.集成APNS推送过程

1.创建推送证书

从钥匙串中创建CRS文件,具体操作步骤见下图:

CSR文件第一步.png

CSR文件第二步.png

CSR文件第三步.png
2.创建推送证书

登录开发者网站->登录账号->创建push推送证书(Development+Distribute)->下载证书->从钥匙串中导出P12证书-发送给公司服务器

创建证书第一步.png

创建证书第二步.png
创建证书第三步.png
3.创建代码

注册APNS推送请求
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中添加如下代码:

//APNS推送
    if (kDeviceSystemVersion >= 10.0) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self;
        UNAuthorizationOptions type = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
        [center requestAuthorizationWithOptions:type completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                NSLog(@"注册APNS成功");
                dispatch_async(dispatch_get_main_queue(), ^{
                    [[UIApplication sharedApplication] registerForRemoteNotifications];
                });
                
            } else {
                NSLog(@"注册APNS失败");
            }
        }];
        
    } else if(kDeviceSystemVersion >= 8.0){
        UIUserNotificationType type = UIUserNotificationTypeAlert|UIUserNotificationTypeSound|UIUserNotificationTypeBadge;
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    } else {
        UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:type];
    }

程序第一次安装的请求弹框如下图:

注册push弹框.png

点击允许后应用接收device token
注册device token成功,调用如下代码:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    //iOS13 后
    NSMutableString *tokenString = [NSMutableString string];
    const char *bytes = deviceToken.bytes;
    int iCount = deviceToken.length;
    for (int i = 0; i < iCount; i++) {
        [tokenString appendFormat:@"%02x", bytes[i]&0x000000FF];
    }
    
    NSLog(@"tokenString = %@", tokenString);
   
    [[NSUserDefaults standardUserDefaults] setObject:tokenString forKey:@"DeviceTokenString"];
    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"autoRemotePush"];
    if (![[NSUserDefaults standardUserDefaults] boolForKey:@"pushToken"] && [[NSUserDefaults standardUserDefaults] objectForKey:@"DeviceTokenString"]) {
        [self pushToken:tokenString];
    }
    
}

注册device token失败,调用如下代码

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
}

将devicetoken 推送给自己公司服务器,推送代码自行编写

4.接收push消息

iOS10以上的通知用UNUserNotificationDelegate接收通知
程序退到后台接收push推送

//ios10之后 应用在后台接收推送消息
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler {
    NSLog(@"%s", __func__);

    NSDictionary * userInfo = response.notification.request.content.userInfo;
    NSDictionary *apsDic = [userInfo objectForKey:@"aps"];

    UIApplication *application = [UIApplication sharedApplication];

    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [self receivedNotification:userInfo application:application];
    }
    else {
        // 判断为本地通知

    }

    // Warning: UNUserNotificationCenter delegate received call to
    completionHandler();  // 系统要求执行这个方法
}

iOS10应用在前台收到push 消息

//ios10 应用在前台是否接收推送消息
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler API_AVAILABLE(ios(10.0)){
    NSLog(@"%s", __func__);
    
    
    NSDictionary * userInfo = notification.request.content.userInfo;
    NSDictionary *apsDic = [userInfo objectForKey:@"aps"];
    
    UIApplication *application = [UIApplication sharedApplication];
    
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [self receivedNotification:userInfo application:application];
    }
    else {
        // 判断为本地通知
        
    }
 
    
}

iOS10 以下系统收到push 消息

//ios3-ios10 收到推送消息
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    [self receivedNotification:userInfo application:application];
    
}

//ios7 点击推送消息进入
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {

    [self receivedNotification:userInfo application:application];
    completionHandler(UIBackgroundFetchResultNewData);
}
5.程序被杀死,点击通知栏的push消息
if ([[launchOptions allKeys] containsObject:UIApplicationLaunchOptionsRemoteNotificationKey]) {//用户是点击通知栏推送启动的
        
        NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
        //        NSDictionary *apsDic = [remoteNotification objectForKey:@"aps"];
        
        //        NSString *message = [apsDic objectForKey:@"alert"];
        //        NSString *badge = [apsDic objectForKey:@"badge"];//红点数量
        //        NSString *sound = [apsDic objectForKey:@"sound"];//声音
        [self receivedNotification:remoteNotification application:application];
        
        NSUserDefaults *notificationDic = [NSUserDefaults standardUserDefaults];
        [notificationDic setObject:remoteNotification forKey:@"notification"];
        
    }else{
        NSLog(@"用户是正常启动的程序");
    }
6.处理推送消息,代码自行编写

三 注意说明

    1. icon角标数字变化

应用图标的applicationIconBadgeNumber变化由 推送消息中的badge决定,接收消息的声音由 推送消息的sound 决定。

  • 2.点击弹框允许后不走- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken方法
    a.推送证书是否有效
    推送证书有效性.png

    b.项目的Push Notifications是否开启
    添加 Push Notifications.png
  • 3.同样的系统,同样的代码,同样的证书,有的手机能收到devicetoken,正常注册APNS推送,有的手机就不能收到devicetoken

极有可能是设备问题,我就遇到了同样的问题,然后用同事手机测试的。

本篇先记录到此,感谢阅读,如有错误,不吝赐教!

你可能感兴趣的:(iOS-简单集成APNS推送)