ios 消息推送流程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ios 消息推送流程相关的知识,希望对你有一定的参考价值。

ios开发:推送通知简述及开发实践
热度 1已有 706 次阅读 2013-10-15 09:23 |个人分类:经验之谈|系统分类:ios| IOS, 推送
一.关于推送通知

推送通知,也被叫做远程通知,是在iOS 3.0以后被引入的功能。是当程序没有启动或不在前台运行时,告诉用户有新消息的一种途径,是从外部服务器发送到应用程序上的。一般说来,当要显示消息或下载数据的时候,通知是由远程服务器(程序的提供者)发送,然后通过苹果的推送通知服务(Apple Push Notification Service,简称apns)推送到设备的程序上。

推送的新消息可能是一条信息、一项即将到期的日程或是一份远程服务器上的新数据。在系统上展现的时候,可以显示警告信息或在程序icon上显示数字,同时,也可以播放警告音。一旦用户注意到程序有新的信息、时间或是数据,他们可以运行程序并访问新的内容。也可以选择忽略通知,这时程序将不会被激活。

iPhone, iPad和iPod touch上同一时刻只有一个app在前台运行。大多数程序在后台运行的时候,可以对某些用户感兴趣的内容做出回应(定时、或数据等)。推送通知能让程序在这些事件发生的时候通知用户。

作为提供者为程序开发和部署推送通知,必须通过iOS Developer Program Portal获得SSL证书。每个证书限用于一个程序,使用程序的bundle ID作为标识。证书有两种用途的:一种是针对sandbox(用于开发和测试),另外一种针对发布产品。这两种运行环境拥有为各自指定的IP地址并且需要不同的证书。还必须为两种不同的环境获取各自的provisioning profiles。

APNS提供了两项基本的服务:消息推送和反馈服务。

消息推送:使用流式TCP套接字将推送通知作为二进制数据发送给APNs。消息推送有分别针对开发和测试用的sandbox、发布产品的两个接口,每个都有各自的地址和端口。不管用哪个接口,都需要通过TLS或SSL,使用SSL证书来建立一个安全的信道。提供者编制通知信息,然后通过这个信道将其发送给APNs。
注:sandbox:   gateway.sandbox.push.apple.com:219
产品接口:gateway.push.apple.com:2195

反馈服务:可以得到针对某个程序的发送失败记录。提供者应该使用反馈服务周期性检查哪些设备一直收不到通知,不需要重复发送通知到这些设备,降低推送服务器的负担。
注:sandbox:feedback.push.apple.com:2196
产品接口:feedback.sandbox.push.apple.com:2196

二.Apple Push Notification的工作机制


下面是一个完整推送流程图
[iOS推送通知_push_01]
从上图,我们可以看到。

      首先是应用程序注册消息推送。
     IOS跟APNS Server要deviceToken。应用程序接受deviceToken。
     应用程序将deviceToken发送给PUSH服务端程序(Provider)。
     服务端程序向APNS服务发送消息。
     APNS服务将消息发送给iPhone应用程序。

无论是iPhone客户端跟APNS,还是Provider和APNS都需要通过证书进行连接的:
[iOS推送通知_push_02]

图中,

1. Provider是指某个iPhone软件的Push服务器,是我们将要开发的服务器。

2. APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器。

上图可以分为三个阶段:

第一阶段:推送服务器(provider)把要发送的消息、目的iPhone的标识打包,发给APNS;

第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone;

第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
三.开发证书和推送证书的配置

1. 使用开发者帐号登录IOS Provisioning ,选择或新建一个App Id,这里以“info.luoyl.iostest”为例
[iOS推送通知_push_1]

2. 创建完后,进入App Id列表,可以看到新建的App Id默认是没有激活推送功能的,点击Configure链接,进入推送功能激活页面:
[iOS推送通知_push_2]

3. 在“Enable for Apple Push Notification service”选项上打勾,然后在行点“configure”按钮:
[iOS推送通知_push_3]
4. 此时会弹出一窗口,点“continue”
[iOS推送通知_push_4]
5. 弹出证书上传页面,证书选择事先做好的“CertificateSigningRequest.certSigningRequest”,然后点“Generate”按钮;
[iOS推送通知_push_5]


6. 接下来会有“Your APNs SSL Certificate has been generated.”提示,点“continue”:
[iOS推送通知_push_6]
7. 下载刚生成的证书“aps_development.cer”到电脑:
[iOS推送通知_push_7]

8. 至此,appid的Development Push SSL Certificate已经变成“Enabled”状态了:
[iOS推送通知_push_8]

9. 制作一开发者测试证书,appid指定为“info.luoyl.iostest”, 下载后双击安装到电脑上:
[iOS推送通知_push_9]

10. 双击在步骤7下载的“aps_development.cer”安装到keychain Access上:
[iOS推送通知_push_10]

11. 选中push Services证书,右键导出证书为个人信息交换(.p12)格式文件,这里我命名为“aps_development.p12”,点存储时会弹出一个密码设置窗口,可留空不填:
[iOS推送通知_push_11]
12. 在终端执行下面的命令,把刚才导出的个人信息交换(.p12)格式文件加密转换成推送服务器的推送证书:
使用OpenSSL

  1、将aps_developer_identity.cer转换成 aps_developer_identity.pem格式。

  openssl x509 -in aps_developer_identity.cer -inform DER -out aps_developer_identity.pem -outform PEM

  2、将p12格式的私钥转换成pem,需要设置4次密码,密码都设置为:和生成p12 文件时你输入的密码一致。

  openssl pkcs12 -nocerts -out PushChat_Noenc.pem -in PushChat.p12

  3、用certificate和the key 创建PKCS#12格式的文件。

  openssl pkcs12 -export -in aps_developer_identity.pem -inkey PushChat_Noenc.pem -certfile PushChat.certSigningRequest -name "aps_developer_identity" -out aps_developer_identity.p12

  这样我们就得到了在.net应用程序中使用的证书文件:aps_developer_identity.p12。

  在.net应用程序中发送通知。

有个开源的类库:apns-sharp。

  地址是:http://code.google.com/p/apns-sharp/

  我们下载源代码,对里面的JdSoft.Apple.Apns.Notifications做相应的调整就能用了。

  我们根据DeviceToken和p12File对JdSoft.Apple.Apns.Notifications.Test做相应的调整,如下图。
转播到腾讯微博
iOS开发如何实现消息推送机制

  这样就OK了。

 

 

 

四.开发带有推送功能的IOS应用

为使应用能支持推送功能,我们的项目配置时要注意:

    Bundle Identifier、Code Signing指定的开发证书绑定的AppId要和推送证书绑定的AppId一致(见下图);
     如果项目中的开发证书在AppId激活推送功能前已经创建了,这时必须重新生成一个。支持推送功能的开发证书会比旧证书多出一项名为 “aps-environment”的授权串,如果继续使用旧证书,在程序启动尝试注册推送功能时会出现“ 未找到应用程序的“aps-environment”的权利字符串 ”的错误;
    测试需要用真机,模拟器不支持。

[iOS推送通知_push_13]

[iOS推送通知_push_13]
[iOS推送通知_push_14]

 

在代码方面,推送的注册、监听和处理都集中在AppDelegate类里:

1.(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
在该方法体里主要实现两个功能:
一是完成推送功能的注册请求,即在程序启动时弹出是否使用推送功能;
二是实现的程序启动是通过推送消息窗口触发的,在这里可以处理推送内容;

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
    {  
        self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];  
        // Override point for customization after application launch.  
        self.viewController = [[[ViewController alloc] init] autorelease];  
        self.window.rootViewController = self.viewController;  
        [self.window setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"background.png"]]];  
        [self.window makeKeyAndVisible];  
        /** 注册推送通知功能, */ 
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];  
          
        //判断程序是不是由推送服务完成的  
        if (launchOptions) {  
            NSDictionary* pushNotificationKey = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];  
            if (pushNotificationKey) {  
                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"推送通知"   
                                                               message:@"这是通过推送窗口启动的程序,你可以在这里处理推送内容" 
                                                              delegate:nil   
                                                     cancelButtonTitle:@"知道了"   
                                                     otherButtonTitles:nil, nil];  
                [alert show];  
                [alert release];  
            }  
        }  
        return YES;  
    }  

2. 接收从苹果服务器返回的唯一的设备token,该token是推送服务器发送推送消息的依据,所以需要发送回推送服务器保存

    - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {  
        NSString* token = [NSString stringWithFormat:@"%@",deviceToken];  
        NSLog(@"apns -> 生成的devToken:%@", token);  
        //把deviceToken发送到我们的推送服务器  
        DeviceSender* sender = [[[DeviceSender alloc]initWithDelegate:self ]autorelease];  
        [sender sendDeviceToPushServer:token ];      
    }  

 

3.接收注册推送通知功能时出现的错误,并做相关处理:

    - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {  
        NSLog(@"apns -> 注册推送功能时发生错误, 错误信息:\n %@", err);  
    } 

4. 接收到推送消息,解析处理

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo  
    {  
        NSLog(@"\napns -> didReceiveRemoteNotification,Receive Data:\n%@", userInfo);  
        //把icon上的标记数字设置为0,  
        application.applicationIconBadgeNumber = 0;  
        if ([[userInfo objectForKey:@"aps"] objectForKey:@"alert"]!=NULL) {  
            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"**推送消息**" 
                                                            message:[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]  
                                                           delegate:self  
                                                  cancelButtonTitle:@"关闭" 
                                                  otherButtonTitles:@"处理推送内容",nil];  
            alert.tag = alert_tag_push;  
            [alert show];  
        }  
    }

以上是关于ios 消息推送流程的主要内容,如果未能解决你的问题,请参考以下文章

iOS推送原理

使用 socket.io 技术实现消息实时推送

极光推送流程

iOS 推送手机消息背后的技术

利用 socket.io 实现消息实时推送

细说 iOS 消息推送