iOS推送相关

名词解释

APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的推送服务器;
Device 安装带有推送服务程序的iPhone手机;
Provider 程序服务器,把需要推送的信息发给 APNS;
DeviceToken  
在Device第一次连接APNS时,由APNS生成的经过加密的连接认证信息。在以后的连接中,无论时Provider到APNS还是APNS到Device 都需要 DeviceToken作为认证。
Payload  需要推送的消息的主体内容。alert-alert消息的消息体,按键标题等badge-显示在程序icon右上角的数字,sound-声音提示文件的文件名,该声音资源文件要在程序包中。

Push的原理

Push 的工作机制可以简单的概括为下图


图中,Provider是一般指某个ios软件的服务器。 

上图可以分为三个阶段。

第一阶段:.net应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。 
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序, 并且按照设定弹出Push通知。


整体流程

1. Device --> 连接-->  APNS  获取 DeviceToken 
2. Device -->连接-->  Provider 提供DeviceToken 


3. Provider侦测需要push的消息生成Notification信息


4. Provider侦把要push的消息推送到APNS
5. APNS把该消息推送到手机


============================================================================================================

具体实现

一、获取推送服务认证书

认证书 是用于服务器与APNS服务器SSL 连接时的认证,而获取p12的前提是获取APNS Assistant。

1. 在apple开发中心生成  App ID(如PushDemo),注意:Bundle Indentifier值格式必须为反向域名格式,如com.bluestar.PushDemo;
2. 单击App ID 的后面的 
Configure; 

3. 在新的页面中,勾选Enable Push Notification Services , 而后点击Configure ,随后出现APNs Assistant,APNs助手会引导生成你的程序与APNs服务器进行SSL连接的认证书App ID specific Client SSL certificate[注释:一般文件名为“aps_developer_identity.cer” 可修改]
4. APNs助手会引导你保存SSL certificate到你的硬盘,保存好后双击,安装到你的keychain;
5. 执行完以上四步,可以点击Done,关闭APNs助手;
6. 启动Keychain Access程序,查看刚才安装的认证,name 为apple Development/Production  push Services。。。 
导出--即获得Certificates.p12 保存好给Provider 服务器使用;


----------------------------------------------------------------------------------------------


无论是iPhone客户端跟APNS,还是Provider和APNS都需要通过证书进行连接的。下面我介绍一下几种用到的证书。

几种证书:

一、*.certSigningRequest文件

   1、生成Certificate Signing Request (CSR):

2、填写你的邮箱和Common Name,这里填写为PushChat。选择保存到硬盘。

这样就在本地生成了一个PushChat.certSigningRequest文件。

二、生成*.p12文件

1、导出密钥,并输入你的密码。

输入你的密码:

这样就生成了一个PushChatKey.p12文件。

三、新建一个App ID 和SSL certificate文件

1、用你的付过费的apple帐号登录到iOS Provisioning Portal。新建一个App ID。

     Description:中输入PushChat

     Bundle Seed ID:默认选择Generate New

     Bundle Identifier:输入com.mysoft.PushChat

    点击提交

这样就会生成下面这条记录:

点击配置:

出现下面界面,点击继续:

这里我们选择前面生成好的PushChat.certSigningRequest文件,点击生成。

正在生成

生成完毕,我们把它下载下来。命名为aps_developer_identity.cer

点击完成,你会发现状态变成Enabled。

到现在为止,我们已经生成了3个文件。

1、PushChat.certSigningRequest

2、PushChatKey.p12 (keyChain导出)

3、aps_developer_identity.cer

现在我们创建一个简单的iPhone应用程序。

1、打开Xcode,选择创建一个View-based Application。命名如下图:

2、在PushChatAppDelegate中的didFinishLaunchingWithOptions方法中加入下面代码:

复制代码
    
    
    
    
- (BOOL)application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions
{
self.window.rootViewController
= self.viewController;
[self.window makeKeyAndVisible];

// Let the device know we want to receive push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge
| UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

return YES;
}
复制代码

通过registerForRemoteNotificationTypes方法,告诉应用程序,能接受push来的通知。

3、在xcode中运行,会弹出下面的提示框:

选择OK。表示此应用程序开启消息通知服务。

在 PushChatAppDelegate.m代码中添加下面方法获取deviceToken 

复制代码
    
    
    
    
- ( void )application:(UIApplication * )application didRegisterForRemoteNotificationsWithDeviceToken:(NSData * )deviceToken
{
NSLog(
@" My token is: %@ " , deviceToken);
}

- ( void )application:(UIApplication * )application didFailToRegisterForRemoteNotificationsWithError:(NSError * )error
{
NSLog(
@" Failed to get token, error: %@ " , error);
}
复制代码


============================================================================================================


从notification(提醒)打开APP(应用程序)到制定viewController


//程序新启动时调用的方法
- ( BOOL ) application : ( UIApplication * ) application didFinishLaunchingWithOptions : ( NSDictionary * ) launchOptions
{
   . . . . . .
   . . . . . .
   NSDictionary *aDict = [ launchOptions objectForKey :
                           UIApplicationLaunchOptionsRemoteNotificationKey ] ;
     if ( aDict != nil ) {
         //判断从推送消息来启动应用程序
         NSDictionary *aps = [ aDict objectForKey : @"aps" ] ;
         [ self notificationOpenApp :aps ] ;    //自定义的open viewController 方法
     }
 
     return YES ;
 
}
//应用程序已经启动的情况下,接收推送提醒的方法
- ( void ) application : ( UIApplication * ) application didReceiveRemoteNotification : ( NSDictionary * ) userInfo
{
     NSDictionary *aps = [ userInfo objectForKey : @"aps" ] ;     
     if ( aps != nil ) {
 
         if ( application . applicationState == UIApplicationStateActive ) {
             //应用程序在前台的时候,这里可以做响应的处理
 
         } else {
             //应用程序在后台时
             [ self notificationOpenApp :aps ] ;
 
         }
 
     }
 
}
//从提醒打开app,并且跳到制定view controller 的方法
- ( void ) notificationOpenApp : ( NSDictionary * ) aps {
     NSString *news_url = [ aps objectForKey : @"news_url" ] ;
     PostViewController *postView = [ [ PostViewController alloc ] initWithNibName : @"PostViewController"
                                                                        bundle :nil ] ;
 
     [ postView setHidesBottomBarWhenPushed :YES ] ;
     postView . sub = [ aps objectForKey : @"alert" ] ; ;
     postView . toURL = news_url ;
     //postView.objNews = nil;
     //由于我的这个布局没有nav所以我用了tabBar里面的Nav
     //如果你的布局里面有nav,可以直接用[self.navigationController pushViewController:....]
     UINavigationController *selectViewNav = [ self . tabBarController . viewControllers objectAtIndex :self . tabBarController . selectedIndex ] ;
     [ selectViewNav pushViewController :postView animated :YES ] ;
     [ postView release ] ;
}

附上一个aps里面的数据结构



============================================================================================================


服务器push证书可以直接从KeyChain中导出直接使用,格式为.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. 将Certificates.p12格式的私钥转换成pem,需要设置4次密码,密码都设置为:abc123。

openssl pkcs12 -nocerts -out aps_developer_key.pem -in Certificates.p12

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

openssl pkcs12 -export -in aps_developer_identity.pem -inkey aps_developer_key.pem -certfile PushTest.certSigningRequest -name "aps_developer_identity" -out aps_developer_identity.p12


1)Java服务器所需的证书为p12格式

openssl pkcs12 -export -in PushChatCert.pem -inkey PushChatKey.pem -out pushCert.p12 -name “apns-cert”

2)PHP服务器所需证书为pem格式

cat PushChatCert.pem PushChatKey.pem > pushCert.pem


============================================================================================================


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


消息推送

测试接口:gateway.sandbox.push.apple.com:2196

产品接口:gateway.push.apple.com:2195

反馈服务

测试接口:feedback.sandbox.push.apple.com2196

产品接口:feedback.push.apple.com:2195


============================================================================================================


关于本地通知

第一步:创建本地推送 
// 创建一个本地推送  
UILocalNotification*notification = [[[UILocalNotificationalloc]init]autorelease];
//设置10秒之后 
NSDate*pushDate = [NSDatedateWithTimeIntervalSinceNow:10]; 
if(notification != nil) {  
    // 设置推送时间  
    notification.fireDate= pushDate;  
    // 设置时区  
    notification.timeZone= [NSTimeZonedefaultTimeZone]; 
    // 设置重复间隔  
    notification.repeatInterval= kCFCalendarUnitDay;  
    // 推送声音  
    notification.soundName= UILocalNotificationDefaultSoundName; 
    // 推送内容  
    notification.alertBody= @"推送内容"; 
    //显示在icon上的红色圈中的数子 
    notification.applicationIconBadgeNumber= 1; 
    //设置userinfo 方便在之后需要撤销的时候使用  
    NSDictionary*info = [NSDictionarydictionaryWithObject:@"name"forKey:@"key"]; 
    notification.userInfo= info;  
    //添加推送到UIApplication        
    UIApplication*app = [UIApplicationsharedApplication]; 
    [appscheduleLocalNotification:notification];  
      

   
第二步:接收本地推送 
- (void)application:(UIApplication*)application didReceiveLocalNotification:(UILocalNotification*)notification{
    UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"iWeibo"message:notification.alertBodydelegate:nilcancelButtonTitle:@"确定"otherButtonTitles:nil];
    [alertshow]; 
    // 图标上的数字减1  
    application.applicationIconBadgeNumber-= 1; 

   
第三步:解除本地推送 
// 获得 UIApplication  
UIApplication*app = [UIApplicationsharedApplication]; 
//获取本地推送数组 
NSArray*localArray = [app scheduledLocalNotifications]; 
//声明本地通知对象 
UILocalNotification*localNotification;  
if(localArray) {  
    for(UILocalNotification*noti inlocalArray) {  
        NSDictionary*dict = noti.userInfo; 
        if(dict) {  
            NSString*inKey = [dict objectForKey:@"key"]; 
            if([inKey isEqualToString:@"对应的key值"]) {  
                if(localNotification){  
                    [localNotificationrelease]; 
                    localNotification = nil; 
                } 
                localNotification = [noti retain]; 
                break; 
            } 
        } 
    } 
      
    //判断是否找到已经存在的相同key的推送 
    if(!localNotification) {  
        //不存在初始化 
        localNotification = [[UILocalNotificationalloc]init]; 
    } 
      
    if(localNotification) {  
        //不推送 取消推送  
        [appcancelLocalNotification:localNotification]; 
        [localNotificationrelease]; 
        return; 
    } 
}


==============================================================================================

关于推送通知常见的错误

推送通知是不可靠的

推送通知是不可靠的!即使APNS(Apple Push Notification Service苹果推送通知服务)服务器接受了推送通知,仍然无法保证该通知最终会被送达。

就你的服务器而言,推送通知会被发出并且遗忘掉;当你将通知发送到APNS后,没有办法查出它所处的状态。通知送达的时间也从几秒到半小时不等。

同样,用户的iPhone不是所有时间都可以收到推送通知。比如,因为指定的端口被封,手机处于一个不允许和APNS连接的WIFI网络。或者手机已经关机了。

APNS将会在手机连接到可用网络后下发从该机器收到的最后一条通知,但是只会尝试有限的时间。一旦发送超时,此条通知就会永远丢失!

------------------------------------------------------------------------------------

推送通知会使开销很大!如果你掌控了需要推送的内容,在你的应用中加入推送功能相当容易和廉价,但是当你有好多用户和数据需要轮询的时候,这个功能就会使得服务器开销庞大(译者注:不一定指价格,包括是资源消耗)。

比如,你打算在自己的RSS订阅更新的时候通知用户,这样做没问题。因为你控制着RSS订阅,并且知道它何时发生变化——当你更新网站内容时——于是你的服务器可以在合适的时候发出通知。

但是如果你的应用是一款RSS阅读器,允许用户添加自定义的链接呢?这种情况下,你需要构建一些机制去检测那些订阅的更新。

实际上,这意味着你的服务器为了检查那些订阅的变化,需要不停的轮询它们。如果你拥有很多用户,你可能不得不安装一堆新服务器去处理这些工作和满足带宽需求。对于这类应用,推送会变得异常昂贵,可能不值得去做。



http://blog.csdn.net/bingwen0210/article/details/6622238

http://www.cnblogs.com/zhuqil/archive/2011/06/05/2070679.html

http://www.iseven-it.com/?p=249

http://blog.csdn.net/mygamezone/article/details/8509906

http://article.ityran.com/archives/194

http://www.cocoachina.com/bbs/read.php?tid=136377&page=1

你可能感兴趣的:(iPhone)