IOS开发之实现App消息推送(最新)(1)

简介: <span style="color:rgb(51,51,51); font-family:Arial; font-size:14px; line-height:26px">好久没有写过博客啦,今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的
好久没有写过博客啦,今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的人会很想了解一下。(ps:网上看了一下虽然有很多讲述推送的好教程,我也是看着一步步学会的,但是这些教程的时间都是去年或者更早时期的,对引导新手来说不是很合适)

第一部分

首先第一步当然是介绍一下苹果的推送机制(APNS)咯(ps:其实每一篇教程都有),先来看一张苹果官方对其推送做出解释的概要图。

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 在CODE上查看代码片 派生到我的代码片
  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. - (void)applicationWillResignActive:(UIApplication *)application  
  58. {  
  59.     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.  
  60.     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.  
  61. }  
  62.   
  63. - (void)applicationDidEnterBackground:(UIApplication *)application  
  64. {  
  65.     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.   
  66.     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.  
  67. }  
  68.   
  69. - (void)applicationWillEnterForeground:(UIApplication *)application  
  70. {  
  71.     // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.  
  72. }  
  73.   
  74. - (void)applicationDidBecomeActive:(UIApplication *)application  
  75. {  
  76.     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.  
  77. }  
  78.   
  79. - (void)applicationWillTerminate:(UIApplication *)application  
  80. {  
  81.     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.  
  82. }  
  83.   
  84. @end  

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

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 在CODE上查看代码片 派生到我的代码片
  1. - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{  
  2.     NSLog(@"---Token--%@", pToken);  
  3. }  
会接收来自苹果服务器给你返回的deviceToken,然后你需要将它添加到你本地的推送服务器上。(很重要,决定你的设备能不能接收到推送消息)。
[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 在CODE上查看代码片 派生到我的代码片
  1. - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{  
  2.   
  3.     NSLog(@"Regist fail%@",error);  
  4. }  
当注册失败时,触发此函数。


2.PHP服务端

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

[php]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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$msgstrlen($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


目录
相关文章
|
9天前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
17天前
|
开发框架 数据可视化 Java
iOS开发-SwiftUI简介
iOS开发-SwiftUI简介
|
7天前
|
移动开发 Android开发 数据安全/隐私保护
移动应用与系统的技术演进:从开发到操作系统的全景解析随着智能手机和平板电脑的普及,移动应用(App)已成为人们日常生活中不可或缺的一部分。无论是社交、娱乐、购物还是办公,移动应用都扮演着重要的角色。而支撑这些应用运行的,正是功能强大且复杂的移动操作系统。本文将深入探讨移动应用的开发过程及其背后的操作系统机制,揭示这一领域的技术演进。
本文旨在提供关于移动应用与系统技术的全面概述,涵盖移动应用的开发生命周期、主要移动操作系统的特点以及它们之间的竞争关系。我们将探讨如何高效地开发移动应用,并分析iOS和Android两大主流操作系统的技术优势与局限。同时,本文还将讨论跨平台解决方案的兴起及其对移动开发领域的影响。通过这篇技术性文章,读者将获得对移动应用开发及操作系统深层理解的钥匙。
|
5天前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
23 7
|
9天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台解决方案
【9月更文挑战第27天】在移动应用开发的广阔天地中,安卓和iOS两大操作系统如同双子星座般耀眼。开发者们在这两大平台上追逐着创新的梦想,却也面临着选择的难题。如何在保持高效的同时,实现跨平台的开发?本文将带你探索跨平台开发的魅力所在,揭示其背后的技术原理,并通过实际案例展示其应用场景。无论你是安卓的忠实拥趸,还是iOS的狂热粉丝,这篇文章都将为你打开一扇通往跨平台开发新世界的大门。
|
10天前
|
XML 移动开发 前端开发
使用duxapp开发 React Native App 事半功倍
对于Taro的壳子,或者原生React Native,都会存在 `android` `ios`这两个文件夹,而在duxapp中,这些文件夹的内容是自动生成的,那么对于需要在这些文件夹中修改的配置内容,例如包名、版本号、新架构开关等,都通过配置文件的方式配置了,而不需要需修改具体的文件
|
10天前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
|
15天前
|
前端开发 iOS开发 开发者
探索iOS开发中的SwiftUI框架
【9月更文挑战第21天】在iOS应用开发的广阔天地中,SwiftUI框架如一股清新之风,为开发者带来了声明式语法的便捷与高效。本文将深入探讨SwiftUI的核心概念、布局方式及数据绑定机制,同时通过实例演示如何运用SwiftUI构建用户界面,旨在引领读者领略SwiftUI的魅力,并激发其对iOS开发新趋势的思考与实践。
33 6
|
14天前
|
安全 Swift iOS开发
探索iOS开发之旅:Swift语言的魅力与挑战
【9月更文挑战第21天】在这篇文章中,我们将一起潜入iOS开发的海洋,探索Swift这门现代编程语言的独特之处。从简洁的语法到强大的功能,Swift旨在让开发者能够以更高效、更安全的方式构建应用程序。通过实际代码示例,我们会深入了解Swift如何简化复杂任务,并讨论它面临的挑战和未来的发展方向。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和知识。
30 4
|
25天前
|
IDE 开发工具 Android开发
安卓与iOS开发对比:平台选择对项目成功的影响
【9月更文挑战第10天】在移动应用开发的世界中,选择正确的平台是至关重要的。本文将深入探讨安卓和iOS这两大主要移动操作系统的开发环境,通过比较它们的市场份额、开发工具、编程语言和用户群体等方面,为开发者提供一个清晰的指南。我们将分析这两个平台的优势和劣势,并讨论如何根据项目需求和目标受众来做出最佳选择。无论你是初学者还是有经验的开发者,这篇文章都将帮助你更好地理解每个平台的特性,并指导你做出明智的决策。