iOS 个推推送原理

你知道吗?APNs和APNs Server不一样。

APNs(英文全称:Apple Push Notification service)中文翻译为:苹果推送通知服务。该技术由苹果公司提供的APNs服务。
APNs Server(英文全称:Apple Push Notification service Server)中文翻译为:苹果推送通知服务服务器。


以下图片来自网络


image.png

从上图我们可以看到:
1、应用程序注册消息推送。
2、iOS从APNs获取device Token,应用程序接收device Token。
3、应用程序将device token发送给PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。


推送原理、流程

1.应用程序Application(简称:APP)注册远程通知。

if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 // Xcode8及以上编译 会调用
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        // 让当前控制器成为UNUserNotificationCenter的代理
        center.delegate = self;
        NSLog(@"当前控制器成为UNUserNotificationCenter的代理");
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay) completionHandler:^(BOOL granted, NSError *_Nullable error) {
            if (!error) {
                NSLog(@"request authorization succeeded!");
            }
        }];
        // 当前应用程序注册远程通知
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        
        
#else // Xcode 7编译会调用
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
        NSLog(@"注册通知了呀");
#endif
    } else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) {
        UIUserNotificationType types = (UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge);
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
         NSLog(@"大于iOS8 注册通知了呀");
    } else {// 小于8
        UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |
                                                                       UIRemoteNotificationTypeSound |
                                                                       UIRemoteNotificationTypeBadge);
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
    }

2.iOS从APNS Server接收到了一个deviceToken。即通过如下代理方法接收deviceToken。
3.然后在该方法中访问 registerDeviceToken:来实现将deviceToken传递给个推服务器。

/** 远程通知注册成功委托   */  
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"\n>>>[DeviceToken Success]:%@\n\n", token);
    
    // 向个推服务器注册deviceToken
    [GeTuiSdk registerDeviceToken:token];
    
}

4.雇主发单的那一刻是触发推送的动作 [这个很重要,这个很重要,这个很重要]。即:雇主发单访问后台提供的某个接口(我们公司是blog_add这个接口)的时候,后台(PHP服务端)拿到前端的订单数据,通过个推提供的SDK将这些订单数据传递给个推服务器,

set_isOffline(true);//是否离线
    $message->set_offlineExpireTime(3600*12*1000);//离线时间
    $message->set_data($template);//设置推送消息类型
    //  $message->set_PushNetWorkType(0);//设置是否根据WIFI推送消息,1为wifi推送,0为不限制推送
    //接收方
    $target = new IGtTarget();
    $target->set_appId($appid);
    $target->set_clientId($clientID);
    //    $target->set_alias(Alias);
    try {
        $rep = $igt->pushMessageToSingle($message, $target);
        sys_log($rep);
        var_dump($rep);
        echo ("

"); }catch(RequestException $e){ $requstId =e.getRequestId(); $rep = $igt->pushMessageToSingle($message, $target,$requstId); sys_log($rep."--"); var_dump($rep); echo ("

"); } } //多推接口案例 function pushMessageToList($cid_list,$msgContent,$keyType,$keyId,$temp_ietm="",$client_notice){ putenv("gexin_pushList_needDetails=true"); $deviceType = 1; $host = HOST; if($deviceType == 1){//苹果 $appid = IOS_APPID; $appkey = IOS_APPKEY; $mastersecret = IOS_MASTERSECRET; } else{//安卓 $appid = ANDROID_APPID; $appkey = ANDROID_APPKEY; $mastersecret = ANDROID_MASTERSECRET; } $igt = new IGeTui($host,$appkey,$mastersecret); //消息模版:透传功能模板 $template = IGtTransmissionTemplateDemo($appid,$appkey,$msgContent,$keyType,$keyId,$temp_ietm,$client_notice); //个推信息体 $message = new IGtListMessage(); $message->set_isOffline(true);//是否离线 $message->set_offlineExpireTime(3600*12*1000);//离线时间 $message->set_data($template);//设置推送消息类型 //$message->set_PushNetWorkType(1);//设置是否根据WIFI推送消息,1为wifi推送,0为不限制推送 $contentId = $igt->getContentId($message); //接收方1 sys_log(4); $cid_list_a = explode(",",$cid_list); $targetList = array(); foreach ($cid_list_a as $cid){ $target1 = new IGtTarget(); $target1->set_appId($appid); $target1->set_clientId($cid); $targetList[] = $target1; } $rep = $igt->pushMessageToList($contentId, $targetList); } //推送到整个APP function pushMessageToApp($msgContent,$keyType,$keyId){ sys_log($msgContent); $deviceType = 1; $host = HOST; if($deviceType == 1){//苹果 $appid = IOS_APPID; $appkey = IOS_APPKEY; $mastersecret = IOS_MASTERSECRET; } else{//安卓 $appid = ANDROID_APPID; $appkey = ANDROID_APPKEY; $mastersecret = ANDROID_MASTERSECRET; } $igt = new IGeTui($host,$appkey,$mastersecret); //消息模版:透传功能模板 $template = IGtTransmissionTemplateDemo($appid,$appkey,$msgContent,$keyType,$keyId); //个推信息体 //基于应用消息体 $message = new IGtAppMessage(); $message->set_isOffline(true); $message->set_offlineExpireTime(3600*12*1000);//离线时间单位为毫秒,例,两个小时离线为3600*1000*2 $message->set_data($template); //$message->set_PushNetWorkType(1);//设置是否根据WIFI推送消息,1为wifi推送,0为不限制推送 $message->set_speed(100);// 设置群推接口的推送速度,单位为条/秒,例如填写100,则为100条/秒。仅对指定应用群推接口有效。 $message->set_appIdList(array($appid)); $rep = $igt->pushMessageToApp($message); } function IGtTransmissionTemplateDemo($appid,$appkey,$msgContent,$keyType,$keyId,$temp_ietm="",$client_notice="default"){ $msg = array( 'keyType' => $keyType, 'keyId' => $keyId, 'msg' => $msgContent, 'nickname' => $temp_ietm ); $msg = json_encode($msg); $template = new IGtTransmissionTemplate(); $template->set_appId($appid);//应用appid $template->set_appkey($appkey);//应用appkey $template->set_transmissionType(2);//透传消息类型 $template->set_transmissionContent($msg);//透传内容 //APN高级推送 $apn = new IGtAPNPayload(); $alertmsg=new DictionaryAlertMsg(); $alertmsg->body=$msgContent; $alertmsg->actionLocKey="ActionLockey"; $alertmsg->locKey=$msgContent; $alertmsg->locArgs=array("locargs"); $alertmsg->launchImage="launchimage"; // IOS8.2 支持 $alertmsg->title=SYS_ZH_NAME; $alertmsg->titleLocKey=SYS_ZH_NAME; $alertmsg->titleLocArgs=array("TitleLocArg"); $apn->alertMsg=$alertmsg; $apn->badge=1; $apn->sound=$client_notice; $apn->add_customMsg("payload","payload"); $apn->add_customMsg("keyType",$keyType); $apn->add_customMsg("keyId",$keyId); $apn->add_customMsg("nickname",$nickname); $apn->add_customMsg("msg",$msgContent); $apn->contentAvailable=0; $apn->category="ACTIONABLE"; $template->set_apnInfo($apn); return $template; } ?>

5.个推服务器通过后台传给它的IOS_APPID,找到IOS_APPID所绑定的CID, 然后个推服务器将订单数据和CID一起发送给了 APNs Server。
个推服务器能直接与APNs Server沟通的原因是:之前已经将deviceToken交给个推服务器了,并且生产证书、开发证书等已经放在个推平台上了。

  • 应用程序之前注册个推的代码,以及在个推提供的代理方法中收到个推返回的cid。我觉得这里有必要粘贴出来。


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
       ...
// 应用程序注册个推
 [GeTuiSdk startSdkWithAppId:kGtAppId appKey:kGtAppKey appSecret:kGtAppSecret delegate:self];
       ... 
}



/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId{
    // 我的clientId为:513a8ec3ae28a63f0dae0499b894f868
  
    // 个推SDK已注册,返回clientId
    NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId);
    //--------------------把clientId通过硬件注册接口(在requestSaveDeviceLogin方法里)传给服务器。。。
    _mychannelid = clientId;
    if (_isLogin) {
        [self requestSaveDeviceLogin];
    }
}

6.APNs在自身的已注册Push服务的设备列表中,查找相应标识的手机设备,并把消息发到手机设备上。

7.手机设备把发来的消息传递给一秒xxAPP, 并且以 通知栏通知/顶部弹框/角标的形式 展示到手机上。

8.在实现的个推提供的代理方法中会收到个推的回调,可以得到个推的透传消息(分为离线和在线),我们一秒xxAPP可以拿到里面的json数据做想要的操作,比如更新UI,文字转语音,跳转界面等等。

.......................

你可能感兴趣的:(iOS 个推推送原理)