iOS-简单集成APNS推送

作者: 329fd8af610c | 来源:发表于2019-10-28 14:01 被阅读0次

    本篇文章对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推送

        本文链接:https://www.haomeiwen.com/subject/turjvctx.html