iOS远程推送

来源:互联网 发布:vlan网络协议报告 编辑:程序博客网 时间:2024/06/04 01:16
  
Paste_Image.png


从上图我们可以看到:
1、应用程序注册消息推送。
2、iOS从APNS Server获取device token,应用程序接收device token。
3、应用程序将device token发送给PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。

关于deviceToken:

deviceToken生成:

远程通知首先要向苹果APNs服务器注册并且生成一个唯一的deviceToken(每个设备的客户端都独一无二)。根据向APNs服务器发送的Token key(包含了设备的UUID和App的Bundle Identifier)。deviceToken将会以NSData对象发送到对应请求的App上。然后App把此deviceToken发送给我们自己的服务器,就是所谓的Provider。Provider收到deviceToken以后进行储存等相关处理,以后Provider根据这个deviceToken来进行消息推送。

deviceToken用处:

deviceToken是推送服务器(Provider)在向应用推送消息时,找到对应的设备以及该设备上对应的应用,从而把此推送消息推送给此应用。

deviceToken唯一性:

deviceToken根据设备唯一标识和客户端唯一标识生成。确保了deviceToken唯一。唯一性并不是说一台设备上的一个应用程序永远只有一个deviceToken,当用户升级系统的时候deviceToken是会变化的。

注册远程通知(获取deviceToken)

注册远程通知的方法

一般都是在App启动完成的时候去注册远程通知注册方法调用一般都在didFinishLaunchingWithOptions:方法中

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {// 在iOS8之前注册远程通知的方法,如果项目要支持iOS8以前的版本,必须要写此方法UIRemoteNotificationTypetypes=UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert;   [[UIApplicationsharedApplication] registerForRemoteNotificationTypes:types];// iOS8之后注册远程通知的方法UIUserNotificationTypetypes=UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert;UIUserNotificationSettings*mySettings =[UIUserNotificationSettingssettingsForTypes:types categories:nil];    [[UIApplicationsharedApplication] registerUserNotificationSettings:mySettings];}

处理注册远程通知的回调方法

// 注册成功回调方法,其中deviceToken即为APNs返回的token

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {   [self sendProviderDeviceToken:deviceToken];// 将此deviceToken发送给Provider}

// 注册失败回调方法,处理失败情况

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {}

处理接收到远程通知消息分两种情况:前台和后台
application: didFinishLaunchingWithOptions:此方法在程序在第一次启动时调用,根据方法内代码判断是否有推送消息。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // userInfo为收到远程通知的内容 NSDictionary*userInfo=launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]; if (userInfo) { // 有推送的消息,处理推送的消息 } return YES;}

各种状态下APP收到消息以及处理:

首先不管在前台还是在后台,如果设置后台模式为Remote Notifications
具体设置方式(或者在info.plist中配置了UIBackgroundModes):如图
TARGETS-Capabilities-Background Modes-Remote Notifications



此时不论App处于Foreground状态还是处于Background状态,收到远程推送消息的时候都会立即调用此方法。

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

这里引入一个概念:
推送唤醒(remote notifications) iOS7以前,当你收到推送消息时,你需要先打开应用,等待应用从网络上获取推送的信息之后,才能将信息呈现出来。而iOS7改变了这一过程。当系统收到推送消息时,不是首先提醒用户,而是唤醒对应的应用,让应用在后台获取对应的信息。当信息处理完成后,再提醒用户。一个很小的改变,但是可以很大的提升用户体验。同样,iOS系统也会限制这种推送消息的频率,防止系统被频繁唤醒影响续航。

此时需要更改推送的payload,如果想要使用推送来唤醒应用运行代码的话,需要在payload中加入content-available,并设置为1。

aps {     content-available: 1       alert: {...} }

1.程序在前台(Foreground)时收到推送:
如果设置remote notifications,那么先执行相对应的方法,在后台收到推送也是如此。
在前台收到通知时,会调用下面这个方法,可以在这个方法里面实现收到通知时刷新或跳转界面的功能;程序在前台收到推送时通知栏不会弹出推送信息

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

2.程序在后台时收到推送:
如果设置remote notifications,那么先执行相对应的方法,在前台收到推送也是如此。
如果用户点击通知栏信息进入程序会调用情况1中的方法,所以在情况1的方法里面需要根据程序在前台还是后台来执行不同操application.applicationState

3.当程序关闭时收到推送:程序关闭时收到推送时,用户点击通知栏信息进入应用的时会调用

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // 在此方法中一定要调用completionHandler这个回调,告诉系统是否处理成功 UIBackgroundFetchResultNewData, // 成功接收到数据 UIBackgroundFetchResultNoData, // 没有接收到数据 UIBackgroundFetchResultFailed // 接受失败 if (userInfo) { completionHandler(UIBackgroundFetchResultNewData); } else { completionHandler(UIBackgroundFetchResultNoData); }}

可操作通知类型收到推送消息时回调方法

// 此两个回调方法对应可操作通知类型,具体使用方法参考以上方法很容易理解,不在详细叙述- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler {}- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler {}

未读消息数量角标设置
设置角标

[UIApplication sharedApplication].applicationIconBadgeNumber=badgeNum;

这个方法可以设置应用程序的角标的数值。但是当程序关闭时,收到推送后我们就不能改变角标数值了。所以建议让服务端推送过来的信息里加上'badge' = 88这个键值对来确定角标的显示数值。这样程序在后台还是关闭,只要显示服务端传给我们的角标值就好了。
不过当我们阅读完一条消息的时需要告诉服务器,并且将[UIApplication sharedApplication].applicationIconBadgeNumber减一。

当客户端杀死情况走本地推送(当客户端开启走—(BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions)。

 if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {        // 当被杀死状态收到本地通知时执行的跳转代码        UILocalNotification *notification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];        NSDictionary *infoDict = [mnResource parseJSONStringToNSDictionary:notification.userInfo[@"info"]];            [self.delegate diaplayAlertWhenReceivePushInfo:infoDict];  }

这里在说明一点在使用个推的时候上传个推平台的.p12要和打包的证书环境一致哦(生产环境和调试环境)

参考文献

  • 苹果开发者文档Local and Remote Notification Programming Guide
  • iOS 万能跳转界面方法

原创粉丝点击