IOS---APNS 消息推送实践

 


首先,需要一个pem的证书,该证书需要与开发时签名用的一致。 具体生成pem证书方法如下:

1. 登录到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action ) 并点击 App IDs

2. 选择对应App ID。(开发与发布不一样的。需注意)

3. 点击App ID旁的“Configure”,然后按下按钮生产 推送通知许可证。根据“向导” 的步骤生成一个签名并上传,最后下载生成的许可证。

4. 通过双击.cer文件将你的 aps_developer_identity.cer 引入Keychain中。

6. 单机“Apple Development Push Services”,导出p12文件,保存为 apns-dev-cert.p12 文件。

7. 扩展“Apple Development Push Services” 对“Private Key”做同样操作,保存为 apns-dev-key.p12 文件。

8. 需要通过终端命令将这些文件转换为PEM格式:

openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12

openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12

9. 如果你想要移除密码,要么在导出/转换时不要设定或者执行:

openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem

10. 最后,你需要将键和许可文件合成为apns-dev.pem文件,此文件在连接到APNS时需要使用:

cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

 

PHP后台写法:

复制代码
<? php   //  这里是我们上面得到的deviceToken,直接复制过来(记得去掉空格)//deviceToken 在测试版本和上线版本上不一样。 //lei ipod touch  $deviceToken = '06fe0a85056f6b9f07fb11a4eed962aaab824b9522660a8bb165b369717159ab' ;   //  Put your private key's passphrase here:  $passphrase = 'abc123456' ;   //  Put your alert message here:  $message = 'My first push test!' ;   // //////////////////////////////////////////////////////////////////////////////  $message =  array('msg'=>'小小说阅读器','title'=>'小小说','url'=>' http://www.apple.com.cn' );   // $message = array('msg'=>'去商品详细页面','itemtype'=>'2','id'=>'192172'); //$message = array('msg'=>'去菜单页面','itemtype'=>'1','zktype'=>'1','order'=>'1','zksubtype'=>'1','zktitle'=>'9.9包邮'); //$message = array('msg'=>'软件升级'); $ctx =  stream_context_create ();   stream_context_set_option( $ctx, 'ssl', 'local_cert', 'ck_dev.pem' );  stream_context_set_option( $ctx, 'ssl', 'passphrase',  $passphrase );   //  Open a connection to the APNS server //这个为正是的发布地址 //$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); //这个是沙盒测试地址,发布到appstore后记得修改哦  $fp =  stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195',  $err$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,  $ctx );   if (! $fp )   exit("Failed to connect:  $err  $errstr" .  PHP_EOL );  echo 'Connected to APNS' .  PHP_EOL ;   //  Create the payload body  $body['aps'] =  array (  'alert' => '逗你玩!哈哈。', 'sound' => 'beep.wav', 'badge' => 1  );   $body['type']=2 ;   $body['data']= $message ;   //  Encode the payload as JSON  $payload = json_encode( $body );   //  Build the binary notification  $msg =  chr(0) .  pack('n', 32) .  pack('H*',  $deviceToken) .  pack('n',  strlen( $payload)) .  $payload ;   //  Send it to the server  $result =  fwrite( $fp$msgstrlen( $msg ));   if (! $result )   echo 'Message not delivered' .  PHP_EOL ;   else  echo 'Message successfully delivered' .  PHP_EOL ;   //  Close the connection to the server fclose( $fp );  ?>
复制代码

 

 

客户端代码:

复制代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions{  
    self.window 
=  [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];   //  Override point for customization after application launch.  
    main 
=  [[MainViewController alloc] init];  
    navMain 
=  [[UINavigationController alloc] initWithRootViewController:main];  
    self.window.rootViewController 
=  navMain;  
    notifiDic 
=  [[NSMutableDictionary alloc] init]; 
    [self initNotification];
    [UIApplication sharedApplication].applicationIconBadgeNumber 
0 ;
NSLog(
@" launchOption==%@ " ,[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]); 
if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey] !=  nil) 

       if (notifiDic.count !=  0 ) {  
        [notifiDic removeAllObjects];
     }  
    [notifiDic setDictionary:(NSDictionary 
* )[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]];     UIAlertView *alert = [[UIAlertView alloc] initWithTitle: @" didFinishLaunching " message:[NSString     stringWithFormat: @" didFinishLaunching:\n%@ ",launchOptions]  delegate:self cancelButtonTitle: @" Cancek "otherButtonTitles: @" OK " , nil];    
     [alert show]; 
     alert.tag 
101
     [alert release];
}  
    self.window.backgroundColor 
=  [UIColor whiteColor]; 
    [self.window makeKeyAndVisible]; 
    return  YES;、
}
 
- ( void )initNotification{ 
     [[UIApplication sharedApplication]registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert 
     
|UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
}

#pragma
 mark
--( void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData * )deviceToken{  
    NSLog(
@" deviceToken: %@ " , deviceToken);
    NSLog(
@" deviceToken===%@ " ,[deviceToken description]); 
    NSRange _range 
= NSMakeRange( 1,[[deviceToken description] length]- 2 ); 
    NSString 
*deviceTokenStr =  [[deviceToken description] substringWithRange:_range];     NSLog( @" deviceTokenStr==%@ " ,deviceTokenStr); 
    deviceTokenStr 
= [deviceTokenStr stringByReplacingOccurrencesOfString: @"  " withString: @"" ];     NSLog( @" deviceTokenStr==%@ " ,deviceTokenStr);  
    UIAlertView 
*alertView = [[UIAlertView alloc] initWithTitle: @" product deviceToken " message:deviceTokenStr  delegate:nil     cancelButtonTitle: @" OK "  otherButtonTitles:nil, nil];
[    alertView show]; [alertView release]; }
 
- ( void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary * )userInfo{ NSLog( @" %s,,,,%@ " ,__func__,userInfo);   if (notifiDic.count !=  0 ) { [notifiDic removeAllObjects]; 
}  
[notifiDic setDictionary:userInfo]; 
UIAlertView 
*alert = [[UIAlertView alloc] initWithTitle: @"" message:[NSString stringWithFormat: @" 受到的通知如下:\n%@ ",userInfo]  delegate:self cancelButtonTitle: @" Cancel " otherButtonTitles: @" OK " , nil]; [alert show]; alert.tag 100 ; [alert release];
}
 
- ( void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError * )err {  
NSLog(
@" %s " ,__func__);
}
复制代码

 

注意点:

1.推送证书都弄好后,项目的开发证书要重新下载一下。

1.反馈服务

Apple 还提供了一个  馈服务 ,你应该定期查询。它提供了一个以前使用过但不再有效的(例如用户卸载了你的iPhone程序)设备令牌列表。你可以从你的数据库中删除这些设备令牌。

本教程不涉及反馈服务的使用。

 

 

2.创建载荷

使用 PHP 很容易根据数组并  换成 JSON而创建载荷:

$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');

$payload = json_encode($payload);

显示 $payload 的内容可以看到传送到APNS  JSON字符串:

{

     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" }

}

这将使消息显示于设备上,触发提升声音并将“1”置于程序图标上。默认按钮“Close”“View”同时会显示于弹出窗口上。

对于 Server Density iPhone程序而言,让用户按下“View”直接进入产生此提示的服务器是很重要的,所以我们增加了额外的自定义值:

$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');

$payload['server'] = array('serverId' => $serverId, 'name' => $name);

$output = json_encode($payload);

当用户按下“View”后,自定义server值将被传递到设备中的程序。JSON 值如下:

{

     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" },

     "server" : { "serverId" : 1, "name" : "Server name")

}

256字节的限制适用于整个载荷,包括自定义字典集。

  

原生接口

Server Density中,一旦产生了一条提示,将建立一个载荷并插入队列中。因此有必要时我们可以同时发送多个载荷。

Apple推荐使用这种方法,因为如果你在发送各载荷时频繁连接和断开,APNS有可能会封锁你的IP

 

3.Push Notification Provider 是一个应用程序,用于通过 APNs 发送推送通知给 iPhone 应用。

通过 APNs 发送推送通知有几个步骤:
1. 
使用前面创建的 SSL 证书与 APNs 通讯;

2. 构造所要发送的消息载体;

3. 发送载体到APNs

APNs 是一个基于流的 TCP socket,你的 provider  SSL 协议与其通讯。推送通知(包括载体)是以二进制流的方式发送的。和APNs 建立连接后,你可以维持该连接并在连接中断之前发送多个通知。

技巧:应避免每发送一次推送通知就建立、关闭一次连接。频繁的建立、关闭连接可能会被 APNs 认为是 DOS 攻击,从而拒绝发送provider 的推送通知发送请求。


你可能感兴趣的:(IOS---APNS)