IOS 推送(本地推送、远程推送、三方推送[极光推送])

1.本地通知【这里只是讲的一种传值方式,本地推送可以在网上搜索 简书里面有很多好文章】

关于本地推送的作用及意义:【后期完善】

实现步骤
大致4步:1创建通知、2注册通知、3实现函数、4删除通知
注意! 下面的内容中没有提到:在使用通知的时候,为了避免重复注册:最好在生命周期的函数中进行 注册 和 删除通知
如下:
//注册通知
- (void)viewWillAppear:(BOOL)animated
{
    、、、、、
}
//在这里删除通知 不然会导致 多次触发通知方法
- (void)viewWillDisappear:(BOOL)animated
{
    //删除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

在A类中创建通知,并设置要传递的参数,和通知哪个方法使用这个参数。这里传递的是一个字典,方法名是: tongzhi


然后在需要获取通知的控制器类的viewDidLoad方法中注册通知


接着在这个类中实现A类中描述的方法,就可以获取到通知的信息了


最后在不使用通知的时候,需要删除通知




2.远程推送

下面两篇文件是兼容IOS的推送。 如果是使用三方【比如极光推送】的话,可以直接看三方的最新文档即可。

iOS开发 iOS10推送讲解(基础篇):http://www.jianshu.com/p/f5337e8f336d

:iOS开发 iOS10推送讲解(高阶1):http://www.jianshu.com/p/3d602a60ca4f



参考来自:http://blog.csdn.net/shenjie12345678/article/details/41120637

如果还有不明白的地方 可以 结合http://www.open-open.com/lib/view/open1431566847716.html 学习。


用推荐方式去实现更好!之后的内容是我的学习过程,方便理解。同样也可以实现

推荐方式:     http://blog.csdn.net/think12/article/details/8863411 from同事推荐[将文件的命名与文中保持一致,后面的命令行直接copy打印即可]


经验:只要正确下载好了配置文件和证书,在发送测试推送的时候 直接在命令行执行 php文件即可


扫描二维码关注公众号,回复: 2241983 查看本文章

注意事项:

*  在程序中注册推送的时候一定要区分系统版本 IO8之前和之后的注册方式是不同的!!!![见下面的绿色背景代码]

   注册推送的目的是想apns发送本应用的id和bundle,注册成功后apns会返回devicetoken

   devicetoken 并不是是唯一的,deviceToken的生成方式就是手机id+应用的bundle,测试版 和 发布版的deviceToken也不一样


1、主要注意证书、AppID、配置文件的设置和命名的规范【这个命名规范非常重要!格式错了 下面的整个过程结束后也得不到预期的结果】

1.2例如 在AppID的命名时 bundle的命名应该为 com.xxx.项目名称如下图



3、在运行程序之前在build setting中的Code Signing的参数设置[如下图]



第一部分、先来看一张苹果官方对其推送做出解释的概要图。

Provider是给你手机应用发出推送消息的服务器,而APNS(Apple Push Notification Service)则是苹果消息推送服务器。你本地的服务器当需要给应用推送一条消息的时候,先要将消息发出到苹果推送服务器,然后再由苹果推送服务器将消息发到安装了该应用的手机。

接下来再看一张解释图:


根据上图的逻辑我来给大家解释一下:

1.你的IOS应用需要去注册APNS消息推送功能。

2.当苹果APNS推送服收到来自你应用的注册消息就会返回一串device token给你(很重要)

3.将应用收到的device Token传给你本地的Push服务器。

4.当你需要为应用推送消息的时候,你本地的推送服务器会将消息,以及Device Token打包发送到苹果的APNS服

5.APNS再将消息推送给目的iphone


第二部分

1.从证书颁发机构颁发证书

打开你mac的钥匙串访问 然后点击钥匙串访问


随后它会弹出一个窗口

用户电子邮件信息

就填写你苹果开发者账号的名称即可(应该是一个邮件名称),点击保存到磁盘的选项,点击继续,显示如下


点击存储,文件名为:CertificateSigningRequest.certSigningRequest 随后将他放在一个文件夹中我们取名push吧!

第三部分


访问苹果开发者网址:https://developer.apple.com/


选中MemberCenter选项,进入登陆页面,用你的苹果开发者账号登陆,过一会网页就会自动跳转到下图。点击红色所选部分

内容进行下一步的操作。


选择Certificates选项,设置证书,如图所示先解释一下


Development选项的作用顾名思义就是用来作为开发使用的证书,Production选项则

是用来发布产品使用的,名称很陌生是不是,之前的开发者网页是没有这一选项的,可能是苹果把他修改了,用这个名称更加能让人

理解吧(字面上解释就是产品么)。两个选项生成证书的步骤是一样的,现在我们使用开发者的选项进行证书的制作,步骤如下:

选择Development选项


点击上面的加号选项,



选择APNS选项(开发么当然是在沙盒环境下了,模拟真实情况),然后Continue


这个AppID我们在下一部分讲如何生成,现在我用的是已经生成好的一个应用ID,继续Continue


这边就要选择在钥匙串访问环节下载下来的CertificateSigningRequest.certSigningRequest文件了,选择并生成


点击下载,得到aps_development .cer,保存到push文件中去。


第四部分

新建一个AppID,选择网页上的AppIDs,然后点击右上角的 “加号”


App的取名只要按照苹果要求的就可以了


然后BundleID是比较重要的,在提交审核以及测试(苹果的TestFlight)和付费环节都需要用到,也只需按照苹果要求来写就好了。


接下来就是对你的应用需要使用苹果的哪些服务进行选择就行了,例如广告,游戏中心,推送,付费等等情况。


最后选择“Submit”选项,在下一个界面中选择“done”选项,这样我们设置AppID的步骤我们就完成了。


第五部分:生成Provisioning Profiles

这个配置概要文件分为两种,一种是为开发使用的,还有一种则是为发布到appStore上面。


创建发布版的ProvisioningProfile与开发版的流程相同,点击Development然后点击右上角的加号


会进入选择何种配置概要文件的界面


我们现在时测试,所以选择“IOS App Development”的选项,在下面的Distribution发布选项中有两个选择,“App Store”以及“Ad hoc”,你可以根据下面的描述

选择你发布所需的选项。点击Continue进入下一步。


选择你上一步创建的AppID,点击Continue 进行下一步


选择你的开发者账号,Continue进行下一步


在这一步上选择你的设备(你只有在这一步上勾选了你的设备,你才能在设备上用这个签名进行调试)。关于如何将你的设备号添加进去也是非常

简单的,选择左侧的"Devices",然后点击右上角的加号,在随后出来的页面上添加你设备的UUID(在XCode中可以查看到)以及name( 可以随便取,自己看的懂就行)

然后Register一下,照着流程走到最后一步就完成了。

好咋们继续回到上面的Provisioning Profile配置环节,当你选好了你的设备后点击“Continue”进入下一页,



输入一个文件名(最好是起的能看懂是干嘛的,当然也可以随便起),点击“Generate”进入下一个页面,在这个页面中就会有一个下载按钮让你下载这个文件,

我们把它下载下来放在Push文件夹中。


第六部分

好了,前期的准备工作都已经做完了,现在让我们开始推送吧!(吼吼)

首先双击我们生成的 “aps_development .cer” 文件,进入钥匙串访问,找到我们的专用秘钥(根据在第二部分中从证书机构颁发证书操作中填写的常用名)


我在第二部分填写的是“silicon”,由于换了一台mac之前安装的没有了,之前没有截图,所以随便找了个图给大家看一下,凭大家的聪明才智应该不难理解吧。

然后右击导出,会弹出如下所示的图。



将他存储到push文件夹中,命名为“push.p12”,在这一步中导出会让你输入密码并验证,你可以自定义一个密码,例如abc123


现在push文件夹中应该有几个文件“aps_development .cer” ,"push.p12",“CertificateSigningRequest.certSigningRequest”以及刚才下下来的配置概要文件。


接下来我们打开终端将他们生成.pem文件

1.把aps_development .cer文件生成.pcm文件,cd到push文件夹下


2.把push.p12文件生成为.pem文件


上边输入的密码则是你导出证书所设的密码,即abc123.接着还会让你输入.pem文件的密码,还是使用abc123好了,防止混淆。

这样我们在push文件夹中就又得到了两个文件,PushChatCert.pem和PushChatKey.pem。


3.把PushChatCert.pem和PushChatKey.pem合并为一个pem文件,


在push文件夹中又多了一个ck.pem文件,以上我们把需要使用的文件都准备好了


接下来就要测试一下啦,是不是很激动~

为了测试证书工作的状况,我们可以使用“telnet gateway.sandbox.push.apple.com 2195”来检测一下,如果显示


则表示成功了。

然后,我们使用我们生成的证书和私钥来设置一个安全的链接去链接苹果服务器

在终端输入如下命令:openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

需要输入密码(abc123 我们刚才所设置的)。

然后他会返回一系列的数据,这里我就粘贴一部分啦:

CONNECTED(00000003)

depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

verify error:num=20:unable to get local issuer certificate

verify return:0

---

Certificate chain

。。。。。(省略)

。。。。。(省略)

。。。。。(省略)

    Start Time: 1416389389

    Timeout   : 300 (sec)

    Verify return code: 0 (ok)

---

测试就到这里啦。。。


第七部分

1.建立推送项目

[objc]  view plain copy 派生到我的代码片
  1. //  
  2. //  AppDelegate.m  
  3. //  TestPushNotifiy  
  4. //  
  5. //  Created by silicon on 14-10-30.  
  6. //  Copyright (c) 2014年 silicon. All rights reserved.  
  7. //  
  8.   
  9. #import "AppDelegate.h"  
  10.   
  11. @implementation AppDelegate  
  12. @synthesize mainView = _mainView;  
  13.   
  14. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions  
  15. {  
  16.     if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])  
  17.     {  
  18.         //IOS8  
  19.         //创建UIUserNotificationSettings,并设置消息的显示类类型  
  20.         UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];  
  21.           
  22.         [application registerUserNotificationSettings:notiSettings];  
  23.           
  24.     } else// ios7  
  25.         [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge                                       |UIRemoteNotificationTypeSound                                      |UIRemoteNotificationTypeAlert)];  
  26.     }  
  27.       
  28.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
  29.     // Override point for customization after application launch.  
  30.     self.window.backgroundColor = [UIColor whiteColor];  
  31.     [self.window makeKeyAndVisible];  
  32.       
  33.     self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];  
  34.     self.window.rootViewController = self.mainView;  
  35.     return YES;  
  36. }  
  37.   
  38. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{  
  39.     NSLog(@"---Token--%@", pToken);  
  40. }  
  41.   
  42. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{  
  43.       
  44.     NSLog(@"userInfo == %@",userInfo);  
  45.     NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];  
  46.       
  47.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil nil];  
  48.       
  49.     [alert show];  
  50. }  
  51.   
  52. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{  
  53.   
  54.     NSLog(@"Regist fail%@",error);  
  55. }  

  56.   
  57. @end  


在appdelegate.m中加入以上代码,

[objc]  view plain copy 派生到我的代码片
  1. if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])  
  2.     {  
  3.         //IOS8  
  4.         //创建UIUserNotificationSettings,并设置消息的显示类类型  
  5.         UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];  
  6.           
  7.         [application registerUserNotificationSettings:notiSettings];  
  8.           
  9.     } else// ios7  
  10.         [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge                                       |UIRemoteNotificationTypeSound                                      |UIRemoteNotificationTypeAlert)];  
  11.     }  

由于ios8的推送跟ios7及以下的不一样,所以需要加判断来注册消息推送。

函数:

[objc]  view plain copy 派生到我的代码片
  1. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{  
  2.     NSLog(@"---Token--%@", pToken);  
  3. }  

会接收来自苹果服务器给你返回的deviceToken,然后你需要将它添加到你本地的推送服务器上。(很重要,决定你的设备能不能接收到推送消息)。

[objc]  view plain copy 派生到我的代码片
  1. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{  
  2.       
  3.     NSLog(@"userInfo == %@",userInfo);  
  4.     NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];  
  5.       
  6.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil nil];  
  7.       
  8.     [alert show];  
  9. }  


这个函数则是当设备接收到来自苹果推送服务器的消息时触发的,用来显示推送消息。

[objc]  view plain copy 派生到我的代码片
  1. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{  
  2.   
  3.     NSLog(@"Regist fail%@",error);  
  4. }  

当注册失败时,触发此函数。


2.PHP服务端

将simplepush.php这个推送脚本也放在push文件夹中

[php]  view plain copy 派生到我的代码片
  1. <?php  
  2.   
  3. // ??????????deviceToken???????????????  
  4. $deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';  
  5.   
  6. // Put your private key's passphrase here:  
  7. $passphrase = 'abc123';  
  8.   
  9. // Put your alert message here:  
  10. $message = 'My first push test!';  
  11.   
  12. ////////////////////////////////////////////////////////////////////////////////  
  13.   
  14. $ctx = stream_context_create();  
  15. stream_context_set_option($ctx'ssl''local_cert''ck.pem');  
  16. stream_context_set_option($ctx'ssl''passphrase'$passphrase);  
  17.   
  18. // Open a connection to the APNS server  
  19. //??????????  
  20.  //$fp = stream_socket_client(?ssl://gateway.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);  
  21. //?????????????appstore??????  
  22. $fp = stream_socket_client(  
  23. 'ssl://gateway.sandbox.push.apple.com:2195'$err,  
  24. $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);  
  25.   
  26. if (!$fp)  
  27. exit("Failed to connect: $err $errstr" . PHP_EOL);  
  28.   
  29. echo 'Connected to APNS' . PHP_EOL;  
  30.   
  31. // Create the payload body  
  32. $body['aps'] = array(  
  33. 'alert' => $message,  
  34. 'sound' => 'default'  
  35. );  
  36.   
  37. // Encode the payload as JSON  
  38. $payload = json_encode($body);  
  39.   
  40. // Build the binary notification  
  41. $msg = chr(0) . pack('n', 32) . pack('H*'$deviceToken) . pack('n', strlen($payload)) . $payload;  
  42.   
  43. // Send it to the server  
  44. $result = fwrite($fp$msg, strlen($msg));  
  45.   
  46. if (!$result)  
  47. echo 'Message not delivered' . PHP_EOL;  
  48. else  
  49. echo 'Message successfully delivered' . PHP_EOL;  
  50.   
  51. // Close the connection to the server  
  52. fclose($fp);  
  53. ?>  

deviceToken填写你接收到的token,passPhrase则填写你的ck.pem设置的密码。

此刻就是见证奇迹的时候了

使用终端进入到push文件夹,在终端输入 php simplepush.php


若显示以上提示则表示推送成功了。

附上一张成功图。


感谢这篇博客的指导:http://blog.csdn.net/showhilllee/article/details/8631734


最后,当成功实现远程推送之后,这里补充一下关于 应用程序是如何接受推推送的 ,内容参考自http://www.2cto.com/kf/201410/344169.html

关于接受APNS推送的函数 都在 Appdelegate.m中间中。
这里有多个函数 用于监听APNS的推送,它们有着各自的区别

3.重要函数

概括来说 就是 APP生命周期的 第一个函数 是在应用没有打开时用来监听并获取推送的
                       而另外的两个函数 则时在应用处于后台 或者 正在运行的时候来监听推送的(这两个函数我的项目中是使用的较短的个,且没有问题)

本文着重叫在App端如何处理推送信息。主要涉及一下几个比较重要的函数,而这些函数都是AppDelegate类中:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

做过iOS 开发的人对这个函数都会很熟悉,这是在程序结束启动,并即将运行时调用的,通常一些初始化的工作可以在这个函数中处理。同样的,推送的相关初始化操作也需要在这个部分完成。这一部分的工作主要分为两部分: 推送类型的注册:
?
1
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationAlert];
这行代码告诉了系统,该程序注册的推送消息类型,通常包括badge、声音以及alert通知。 处理程序没有启动时的推送消息: 如果是程序正在运行或者说程序正在后台,那么这个时候处理推送消息的工作都是在:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 或者:

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

中完成。但是如果用户点击推送通知的时候程序还没有被启动,这个时候以上两个函数都是接收不到用户的推送通知的,这个时候需要在application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*) launchOptions 函数里面进行处理。而推送消息的相关信息就存储在launchOptions这个字典里。具体参照如下代码:
?

可以从 launchOptions  字典中 找出推送中的内容,并判断推送的需求,另外,这个字典里面的 key 和 value 是可以在服务端自定义一些值的
1
2
3
4
5
6
7
8
9
10
NSDictionary* pushInfo = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
if (pushInfo)
{
    NSDictionary *apsInfo = [pushInfo objectForKey:@"aps"];
    if(apsInfo)
    {
        //your code here
    }
     
}


- (void)application:(UIApplication *)applicationdidRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken & - (void)application:(UIApplication *)applicationdidFailToRegisterForRemoteNotificationsWithError:(NSError *)error

为了让device端可以接收到推送消息,需要将设备的token传送到苹果的服务器,这个token就相当于设备的识别码,每一台苹果设备都有唯一的token,苹果的服务器就是通过这个token找到对应的设备,并传送相应地消息。这两个函数就是在传送token成功或者失败后调用的,用户在对应的函数里面做一些相应地处理。 

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo和

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

都是程序在运行过程中(无论当前程序处于前台还是后台)接收到推送消息的处理函数。根据苹果的官方文档,建议大家使用

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

因为前者在程序处于后台的时候是无法接收到推送信息的(经实测-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo其实可以接收到,不知道是怎么回事,希望大虾解疑)。另外就是-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler 还有一个作用。根据苹果给出的文档,系统给出30s的时间对推送的消息进行处理,此后就会运行CompletionHandler程序块。

在处理这类推送消息(即程序被启动后接收到推送消息)的时候,通常会遇到这样的问题,就是当前的推送消息是当前程序正在前台运行时接收到的还是说是程序在后台运行,用户点击系统消息通知栏对应项进入程序时而接收到的?这个其实很简单,用下面的代码就可以解决:

?
1
2
3
4
5
6
7
8
9
10
11
12
void  application:(UIApplication*)application didReceiveRemoteNotification:NSDictionary)userInfo fetchCompletionHandler:((^)UIBackgroundFetchResult)completionHandler{
if  (application.applicationState == UIApplicationStateActive) {
         NSLog(@ "active" );
         //程序当前正处于前台
     }
     else  if (application.applicationState == UIApplicationStateInactive)
     {
         NSLog(@ "inactive" );
         //程序处于后台
         
     }
}

4.三方推送[极光推送]

2016-04-21时更新(如果看的时候 距离这个时间跨度较大了,建议直接去官网查看,有不会的可以访问极光的技术论坛询问)
之前虽然知道,但是一只没有用过三方推送。其实用三方推送是很方便的。也省去了很多客服端盒服务端的开发难度。同时三推送也做了很多性能的优化。
好,不废话了。

其实这部分内容相当简单,概括的说就是:
1,去官网下载ios端的开发库,目前就是一个静态库。下载的同时会包含官方的demo和一个开发文档。
2,根据开发文档的流程配置就行。大致是:2.1导入静态库,2.2导入支持的框架,2.3添加一个属性列表,2.4在capabilities中设置background modes勾选远程推送。如图
然后就是在注册极光推送的账号,下载推送的开发者证书,道出p12文件 并上传到极光推送的网站上去,获取到appkey,然后就在Appdelegate.m文件中注册和接收远程推送即可。详细内容参考demo就行。比起之前的实现推送的方式来说,这是最简单的。也可以在极光的网站上直接发送推送。记得,推送只能在真机上测试。 到这里内容就全部over了。

猜你喜欢

转载自blog.csdn.net/wokenshin/article/details/50331443