01-实现步骤

原文地址:原文地址

一.关于推送通知

推送通知,也被叫做远程通知,是在iOS3.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跟APNS Server要deviceToken。应用程序接受deviceToken。
应用程序将deviceToken发送给PUSH服务端程序(Provider)。
服务端程序向APNS服务发送消息。
APNS服务将消息发送给iPhone应用程序。

无论是iPhone客户端跟APNS,还是Provider和APNS都需要通过证书进行连接的:

图中,

  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”为例
  2. 创建完后,进入App Id列表,可以看到新建的App Id默认是没有激活推送功能的,点击Configure链接,进入推送功能激活页面:
  3. 在“Enable for Apple Push Notification service”选项上打勾,然后在行点“configure”按钮:
  4. 此时会弹出一窗口,点“continue”


  5. 弹出证书上传页面,证书选择事先做好的“CertificateSigningRequest.certSigningRequest”,然后点“Generate”按钮;
  6. 接下来会有“Your APNs SSL Certificate has been generated.”提示,点“continue”:
  7. 下载刚生成的证书“aps_development.cer”到电脑:
  8. 至此,appid的Development Push SSL Certificate已经变成“Enabled”状态了:
  9. 制作一开发者测试证书,appid指定为“info.luoyl.iostest”, 下载后双击安装到电脑上:
  10. 双击在步骤7下载的“aps_development.cer”安装到keychain Access上:
  11. 选中push Services证书,右键导出证书为个人信息交换(.p12)格式文件,这里我命名为“aps_development.p12”,点存储时会弹出一个密码设置窗口,可留空不填:
  12. 在终端执行下面的命令,把刚才导出的个人信息交换(.p12)格式文件加密转换成推送服务器的推送证书:

[cpp] view plain copy

openssl pkcs12 -clcerts -nokeys -out cert.pem -in aps_development.p12
openssl pkcs12 -nocerts -out key.pem -in aps_development.p12
openssl rsa -in key.pem -out key.unencrypted.pem
cat cert.pem key.unencrypted.pem > iostest_push_dev.pem

[图片上传中。。。(14)]
上面的命令在执行时有4处是需要输入密码的,其中1和2直接回车,3必须设定一个key如“push”,在4处输入3设定的key “push”;命令执行完后生成的“iostest_push_dev.pem”就是我们推送服务器要使用的推送证书;
经过以上步骤的配置,已经完成了开发推送功能所需要的条件了,接下来将会新建一个ios应用来体验完成推送功能,在ios应用需要实现的接口。

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

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

在代码方面,推送的注册、监听和处理都集中在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];     
    }     
}     

通过上面的代码,基本推送功能的开发已经完成了。最后附件上面代码中所需用到的DeviceSender的类文件,需要将其头文件导入到AppDelegate中。下面是DeviceSender类的.h和.m文件的下载地址:
http://download.csdn.net/detail/enuola/5100134

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容