iOS 消息推送 详解

来源:互联网 发布:我的老婆是警花知君 编辑:程序博客网 时间:2024/06/03 21:25


如果英文好的话,建议查看官方文档:https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW9

什么是远程消息推送功能

苹果给iOS和Mac添加了消息推送的功能,使得我们可以通过后台服务器给应用程序(APP)发送消息,不管APP是否正在使用,比如邮箱的来件提示功能。这项服务被称为Apple Push Notification service(APNs)。里面一共涉及到四个角色:APP、设备、APNs和应用后台服务器(Provider),其中APP、后台服务器和APNs之间使用deviceToken唯一的标识一个用户。

推送服务的工作流程:

  1. APP向系统注册推送服务。

  2. 设备从APNs请求deviceToken。

  3. 通过代理方法将deviceToken返回给APP。

  4. APP将deviceToken发送给应用后台服务器(Provider)。

  5. 应用后台服务器保存deviceToken,然后在需要推送通知的时候,给APNs发送信息,使用deviceToken标识所要送达的客户端。

  6. APNs将后台服务器发过来的数据推送到设备。

  7. 设备将消息分发给应用程序。

在使用推送功能的时候,需要在开发者中心创建支持Push Notification的证书,并且将证书和私钥用于应用后台服务器与APNs之间通信。

环境配置

使用推送服务有一些必要条件:

  1. 开发者账号。

  2. iOS真机(iPhone、iPad、iPod)。

  3. 后台服务器。

  4. 网络。

为了使应用支持推送服务,需要配置Provisioning Profile使它支持Push,和普通的Provisioning Profile文件一样分为Development和Production两个版本。我们使用Development版进行测试。

接下来创建一个用于应用后台服务器和APNs服务器通信时使用的SSL证书和私钥。

1 .在钥匙串访问工具中获取证书请求文件(CSR)。

2 .保存请求文件。

3 .从钥匙串访问工具中导出私钥,将它保存为PushKey.p12,输入密码abcde。千万别把密码给忘了哈,等下要用的。

4 .登陆iOS Dev Center创建APP ID和*Provisioning Profile*。

5 .创建新的App ID时,要注意开启Push Notification

6 .最后App ID看起来是这样的。

7 .到这一步,虽然已经开启了推送服务,但是还需要进一步配置,点击Setting按钮进行设置。

8 .滚动到最下面,需要创建SSL证书(Create Certificate),测试环境使用Development SSL Certificate

9 .查看证书创建步骤和说明,上传第1步得到的证书请求文件。

10 .下载生成好的证书,命名为aps_development.cer

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

1、Push.certSigningRequest

2、Push.p12

3、aps_development.cer


接下来就是进行推送测试阶段:

到了这里,我们有多种选择继续了。

1 .使用第三方小工具PushMeBaby模拟应用后台服务器发送推送信息。

2 .搭建应用后台服务器发送推送信息。

                  

下面先试一试第一种方法,使用PushMeBaby。这是一个开源的Mac小程序,将ApplicationDelegate.m中添上deviceToken和证书的位置。

- (id)init {    self = [super init];    if(self != nil) {        //55e231f0 86257e00 eed93ac6 47b52c78 12abe79f 9c9d1c67 4c770589 36c9a235 ---- 保留空格        self.deviceToken = @"";        //推送内容,JSON格式        self.payload = @"{\"aps\":{\"alert\":\"乔帮主乔帮主乔帮主\",\"badge\":1}}";        //获取证书路径        self.certificate = [[NSBundle mainBundle] pathForResource:@"aps_development" ofType:@"cer"];    }    return self;}

deviceToken的获取在下面的代码部分。

一定要记得将刚才的aps_development.cer证书文件添加到项目中,当然也可以直接将证书路径赋值给self.certificate。

接下来试一试第二种方法:

发送通知的后台应用程序如果用php, java 实现,除了需要知道deviceToken之外,还需要一个与APNS连接的证书。

这个证书可以通过我们前面生成的文件中得到。


1)我们使用PHP来发送通知(其实运行PHP并不需要另外搭建服务器和下载程序,Mac默认支持PHP运行,不信到命令行运行一下php)。

这种方式相对来说麻烦一些,但是也是实际使用的时候会采取的方式。我们需要进一步处理私钥和证书文件。

1 .首先将证书文件和私钥处理成单个方便使用的pem文件,假设CSR、p12和cer文件都放在桌面上。

$ cd ~/Desktop$ls aps_development.cerCertificateSigningRequest.certSigningRequestPushKey.p12

2 .将aps_development.cer转换为pem文件。

$ openssl x509 -in aps_development.cer -inform der -out PushCert.pem$ lsaps_development.cerCertificateSigningRequest.certSigningRequestPushCert.pemPushKey.p12

3 .将p12私钥文件转换为pem文件。

$ openssl pkcs12 -nocerts -out PushKey.pem -in PushKey.p12 Enter Import Password:MAC verified OKEnter PEM pass phrase:Verifying - Enter PEM pass phrase:

4 .将两个文件合成同一个。

$ cat PushCert.pem PushKey.pem > ck.pem$ lsaps_development.cerCertificateSigningRequest.certSigningRequestck.pemPushCert.pemPushKey.pem PushKey.p12

5 .测试证书是否有效。

$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem

如果有效的话,会输出一堆信息,并且建立连接,否则不会成功建立连接。

6 .使用PHP进行测试,下载SimplePush.php,修改文件并填入deviceToken和密码。在终端运行该代码。

$ php simplepush.php Connected to APNSMessage successfully delivered

成功发送推送消息。

2)JAVA来发送通知

1、将aps_development.cer转换成aps_development.pem格式

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

2、将p12格式的私钥转换成pem

  1. openssl pkcs12 -nocerts -out Push_Noenc.pem -in Push.p12  

3、创建p12文件

  1. openssl pkcs12 -export -in aps_development.pem -inkey Push_Noenc.pem -certfile Push.certSigningRequest -name "aps_development" -out aps_development.p12  

这样我们就得到了在.net或java等后台应用程序中使用的证书文件:aps_development.p12

核心代码

import javapns.back.PushNotificationManager;import javapns.back.SSLConnectionHelper;import javapns.data.Device;import javapns.data.PayLoad; public class MainSend{    public static void main(String[] args) throws Exception    {        try        {            //从客户端获取的deviceToken            String deviceToken = "3a20764942e9cb4c4f6249274f12891946bed26131b686b8aa95322faff0ad46";            System.out.println("Push Start deviceToken:" + deviceToken);            //定义消息模式            PayLoad payLoad = new PayLoad();            payLoad.addAlert("消息推送测试!");            payLoad.addBadge(4);            payLoad.addSound("default");            //注册deviceToken            PushNotificationManager pushManager = PushNotificationManager.getInstance();            pushManager.addDevice("iPhone", deviceToken);            //连接APNS            String host = "gateway.sandbox.push.apple.com";            int port = 2195;            String path = "/Users/iMilo/Work.localized/iShop/project/service/iPush/";            String certificatePath = (path + "src/ipush/iPush.p12");            //certificatePath 步骤一中生成的*.p12文件位置            String certificatePassword = "Love24mm";            pushManager.initializeConnection(host, port, certificatePath, certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);            //发送推送            Device client = pushManager.getDevice("iPhone");            pushManager.sendNotification(client, payLoad);            //停止连接APNS            pushManager.stopConnection();            //删除deviceToken            pushManager.removeDevice("iPhone");            System.out.println("Push End");        }        catch (Exception ex)        {            ex.printStackTrace();        }    }}

iOS端代码实现

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    //判断是否注册了远程通知    if (![application isRegisteredForRemoteNotifications]) {        UIUserNotificationSettings *uns = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound) categories:nil];        [application registerUserNotificationSettings:uns];        //注册远程通知        [application registerForRemoteNotifications];    }    return YES;}//获取DeviceToken成功- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{    NSLog(@"DeviceToken: {%@}",deviceToken);    //这里进行的操作,是将Device Token发送到服务端} //注册消息推送失败- (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error{    NSLog(@"Register Remote Notifications error:{%@}",[errorlocalizedDescription]);} //处理收到的消息推送- (void)application:(UIApplication *)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfo{    NSLog(@"Receive remote notification : %@",userInfo);    UIAlertView *alert =    [[UIAlertView alloc] initWithTitle:@"温馨提示"                               message:@"推送成功!"                              delegate:nil                     cancelButtonTitle:@"确定"                     otherButtonTitles:nil];    [alert show];    [alert release];}

下面附上另外一份比较详细的文章,感谢这位博友分享http://blog.csdn.net/showhilllee/article/details/8631734

另一位博友的三篇文章:(

http://blog.sina.com.cn/s/blog_6afb7d800101fa29.html

http://blog.sina.com.cn/s/blog_6afb7d800101fafl.html

http://blog.sina.com.cn/s/blog_6afb7d800101faiz.html

以及另一位博友摘录的国外的文档:http://blog.csdn.net/kepoon/article/details/22384375


另附上对Certificate、App Id、Identifiers 和 Provisioning Profile理解的文章:http://www.th7.cn/Program/IOS/201406/218729.shtml

0 0
原创粉丝点击