1.推送通知流程简述:
流程图:
a.app应用首先需要注册通知,第一次安装应用会提示用户是否需要接收这些通知,用户确认后才能接收到这些通知
b.app通过ios操作系统到apns注册通知后,apns会给app下发一个唯一的token令牌
c.app接收到token令牌信息后,将令牌发送给我们的服务器
d.当需要发送通知时,服务器会象apns发送通知,发送的内容包括(token令牌,content通知的内容,和SSL key证书发)
e.当apns验证通过后就会吧通知的内容发送给app
2.推送通知的基本要求:
a.必须要有iphone或ipad的设备,模拟器上无法对推送通知进行测试,必须在真机上测试
b.需要加入ios开发者计划(99美金/年),生成推送证书
c.连接互联网的服务器,因为推送的发起者是服务器端(provider)
3,推送通知的内容解析:
服务器端(provider)负责创建消息推送通知,一个推送服务的通知一般包含“设备令牌”和“负载”(定义的json信息的属性列表,负载最大为256字节)。
对于每个推送通知,服务器端(provider)必须构建一个严格遵守RFC 4627的JSON格式的字典。
该字典必须包含一个键名为aps的字典,而aps的字典里包含一个或多个属性,这些属性如下:
a.提示用户的警告信息 b.一个提示声音 c.显示app应用程序的角标
消息内容如下:
- {
- "aps":
- {"alert":"警告信息",
- "badge":6, //角标的值
- "sound":"提示声音.caf",
- "newID":"4987", //自定义字段
- "other":"钓鱼岛是我们中国的"
- }
- }
4.推送通知的局限性:
a.推送通知是不可靠的,不同的设备之间他们的推送时间存在不一致
b.推送通知也可能不能被推送到指定的设备,原因可能是wifi环境下端口被封,设备处于关机状态,又或者是网络环境差,都可以影响通知无法推送到指定的设备,
apns会尽量与设备“握手”以建立连接,但它只会在有限的时间之内,如果超时,apns会将这些推送消息永久删除
5.注册推送证书
。。。。。。。。。。。。。。。。。。
6.将证书制作成.pem文件给服务器
pem文件由私钥和push ssl证书合成,当服务器端与apns服务器建立连接时,需要对该文件进行验证
准备私钥和push ssl证书
a.将证书制作成.pem文件
打开终端应用,进入到push ssl目录下(例:如果要生成到桌面的APNS文件夹下,在终端输入“cd /Users/userName/Desktop/APNS”)
然后输入命令:openssl x509 -in aps_developer_indentity.cer -inform der -out push_developer_cer.pem(此命令会将文件aps_developer_indentity.cer转换成.pem文件
push_developer_cer.pem,运行命令后,在桌面的APNE文件夹下会多出push_developer_cer.pem文件)
b.将私钥制作成.pem文件
在终端输入命令:openssl pkcs12 -nocerts -out pushKey.pem -in TestPushKey.p12 ,输入命令后,终端提示输入秘匙密码,
输入密码后,终端提示输入新密码和确认新密码。成功后产生新的文件pushKey.pem。
c.合并证书和私钥
将上述新产生的文件合并,在终端输入命令:
cat push_developer_cer.pem pushKey.pem > ck.pem
完成后生成ck.pem文件,该文件在服务器和apns服务器建立连接时,用于验证。
d.测试证书是否有效
在终端输入命令:openssl s_client -connect geteway.sandbox.push.apple.com:2195 -cert push_developer.cer.pem -key pushKey.pem
如果测试成功,会显示大量的openssl消息。当你任意输入几个字符后,服务器会提示断开
7.代码
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
- self.window.backgroundColor = [UIColor whiteColor];
- [self.window makeKeyAndVisible];
- // 当我们的程序没有被启动时,provider(服务器)发送了一条感兴趣的消息,通过launchOptions字典来获取内容
- NSDictionary *remoteDic = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
- if (remoteDic) {
- label.text = [[remoteDic objectForKey:@"aps"] objectForKey:@"alert"];//获取alert中的数据
- }
- // 注册通知(声音、标记、弹出窗口)
- [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
- return YES;
- } /
- // APNS -> token(令牌)接收到apns下发的token
- - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
- {
- NSLog(@"deviceToken : %@", deviceToken);
- //将token发送给我们的服务器端
- }
- // error
- - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
- {
- NSLog(@"error : %@", [error localizedDescription]);
- }
- // 接受到感兴趣的内容(挂起时调用代理方法),处理接收到的消息
- - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
- {
- // NSLog(@"userInfo : %@", [[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
- UILabel *label = (UILabel *)[self.window viewWithTag:101];
- label.text = [[userInfo objectForKey:@"aps"] objectForKey:@"other"];
- }
- - (void)applicationDidBecomeActive:(UIApplication *)application
- {
- [application setApplicationIconBadgeNumber:0];//将应用角标设置为0
- // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
- }