iOS远程推送详解

iOS远程推送详解_第1张图片
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


iOS远程推送详解_第2张图片

此时不论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];
     
  }

到现在为止做iOS 推送也差不多算入行了吧(都是用的个推)
昨天调试个推送也让我蛋疼,调试了一晚上,其他系统的没什么问题,就有个手机是iOS 10.0.2的系统,不知道为什么走不通apns。

遇到这些问题不要慌,先定为到问题。下面列举自己踩过的个推方面的坑:

1.打包的证书与个推后台的证书环境不一致,导致推送失败。
2.服务端忘记设置了个推安卓和ios的key,没有区分,所以会向客户端下发两条推送,那是我解析的时候是蒙蔽的,json解析出来怎么会有两种key完全不同的字典。这时候alert很大几率显示null且不能跳转,因为你解析不出来。
3.上面那种讲到的情况,自己分析应该是

这里在说明一点在使用个推的时候上传个推平台的.p12要和打包的证书环境一致哦(生产环境和调试环境)
参考:http://www.jianshu.com/p/4b947569a548

你可能感兴趣的:(iOS远程推送详解)