个推配置参考个推文档 http://docs.getui.com/mobile/ios/overview/
个推官方技术人员说明:
iOS的消息是分两部分的:一部分是走APNS的通知栏, 另一部分是走我们通道的透传消息 ;这两部分是服务端推送代码里面你们的人员会设定好的,分别是两个不同的方法 ,如果消息下发的时候,你客户端是在后台的(也就是客户端是离线)那么会收到APNS的通知;透传消息就进离线了,只有你下次在线的时候 (也就是下次应用到前台的时候)才会下发下来。 如果下发的时候应用是在前台的,那这样的话客户端就直接收到透传消息了,APNS那部分消息就不会下发了。
app没启动,或者在后台,或者锁屏,都是离线状态,你推送透传时,首先走的是苹果的apns通道,此时会收到apn通知,点开通知,进入应用,app就在线了,就会走个推通道,下发透传消息
补充说明:
在个推后台推送消息有任务中和任务停止操作的区别,如下图:
根据上图中的操作,测试结果如下:
在个推后台推送消息,收到推送消息后续操作
- App在前台时,走透传消息
- App在后台时,任务中,点AppIcon唤起App,走透传消息
- App在后台时,任务中,点推送消息唤起App,同时走透传消息和APNS
- App在后台时,任务中,点通知栏消息唤起App,同时走透传消息和APNS
- App在后台时,任务停止,点AppIcon唤起App,收不到推送消息
- App在后台时,任务停止,点击推送消息唤起App,走APNS
- App在后台时,任务停止,点击通知栏消息唤起App,走APNS
- App未启动时,任务中,点击AppIcon启动App,走透传消息
- App未启动时,任务中,点击推送消息启动App,同时走透传消息和APNS
- App未启动时,任务中,点击通知栏推送消息启动App,同时走透传消息和APNS
- App未启动时,任务停止,点击AppIcon启动App,收不到推送消息
- App未启动时,任务停止,点击推送消息启动App,走APNS
- App未启动时,任务停止,点击通知栏消息启动App,走APNS
在服务端推送消息,收到推送消息后续操作(相当于在个推后台任务中操作)
- App在前台时,走透传消息
- App在后台时,点击AppIcon唤起App,走透传消息
- App在后台时,点击推送消息唤起App,同时走透传消息和APNS
- App在后台时,点击通知栏推送消息唤起App,同时走透传消息和APNS
- App未启动时,点击AppIcon启动App,走透传消息
- App未启动时,点击推送消息启动App,同时走透传消息和APNS
- App未启动时,点击通知栏消息启动App,同时走透传消息和APNS
iOS10以上用新API实现
1.注册个推
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 个推
[GeTuiSdk startSdkWithAppId:GetuiAppId appKey:GetuiAppKey appSecret:GetuiAppSecret delegate:self];
// 注册APNS
[self registerUserNotification];
// 是否允许SDK 后台运行(这个一定要设置,否则后台apns不会执行)
[GeTuiSdk runBackgroundEnable:true];
return YES;
}
2.注册用户通知
/** 注册用户通知 */
- (void)registerUserNotification
{
/*
注册通知(推送)
申请App需要接受来自服务商提供推送消息
*/
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!granted) {
[self showNoticeAlert];
}
}];
// 注册通知
[[UIApplication sharedApplication] registerForRemoteNotifications];
}else {
if ([UIApplication instancesRespondToSelector:@selector(registerUserNotificationSettings:)]) {
// 定义用户通知类型(Remote.远程 - Badge.标记 Alert.提示 Sound.声音)
UIUserNotificationType types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
// 定义用户通知设置
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
// 注册用户通知 - 根据用户通知设置
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) {
[self showNoticeAlert];
}
}
}
}
#pragma mark - iOS 10以下注册通知
/** 已登记用户通知 */
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
// 注册远程通知(推送)
[application registerForRemoteNotifications];
}
3.远程通知(推送)回调
#pragma mark - 远程通知(推送)回调
/** 远程通知注册成功委托 */
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// [3]:向个推服务器注册deviceToken 为了方便开发者,建议使用新方法
[GeTuiSdk registerDeviceTokenData:deviceToken];
NSLog(@"\n>>>[DeviceToken(NSData)]: %@\n\n", deviceToken);
}
4.GeTuiSdkdelegate 注册回调,获取CID信息
#pragma mark - GeTuiSdkdelegate 注册回调,获取CID信息
/** SDK启动成功返回cid */
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId {
//个推SDK已注册,返回clientId
NSLog(@"\n>>>[GeTuiSdk RegisterClient]:%@\n\n", clientId);
}
/** SDK遇到错误回调 */
- (void)GeTuiSdkDidOccurError:(NSError *)error {
//个推错误报告,集成步骤发生的任何错误都在这里通知,如果集成后,无法正常收到消息,查看这里的通知。
NSLog(@"\n>>>[GexinSdk error]:%@\n\n", [error localizedDescription]);
}
5.GeTuiSdkdelegate 透传消息回调
/** SDK收到透传消息回调 */
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {
// [4]: 收到个推消息
NSString *payloadMsg = nil;
NSDictionary *payloadDict = nil;
if (payloadData) {
payloadMsg = [[NSString alloc] initWithBytes:payloadData.bytes length:payloadData.length encoding:NSUTF8StringEncoding];
NSData *data = [[NSData alloc] initWithData:[payloadMsg dataUsingEncoding:NSUTF8StringEncoding]];
payloadDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
}
if (payloadDict == nil) {
return;
}
//isAPNS 针对同时走APNS和透传消息时在APNS代理方法中处理,透传消息不做处理
if (self.isAPNS) {
self.isAPNS = NO;
return;
}
NSDictionary *userInfo = [payloadDict dictionaryValueForKey:@"message"];
NSString *string = [userInfo stringValueForKey:@"schema"];
NSString *title = [payloadDict stringValueForKey:@"title"];
NSString *message = [payloadDict stringValueForKey:@"content"];
NSString *type = [payloadDict stringValueForKey:@"type"];
// offLine 为YES时表示是离线消息
// 离线消息并且非营销类的消息不做弹窗处理
// operation 营销类push消息
if (offLine && ![type isEqualToString:@"operation"]) {
return;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (string.length == 0 || [string isEqualToString:StringToastNone]) {
[UIAlertController alertViewController:title message:message cancelActionTitle:@"我知道了" otherActionTitle:nil cancelBlock:nil otherBlock:nil];
}else {
[UIAlertController alertViewController:title message:message cancelActionTitle:@"取消" otherActionTitle:@"前往" cancelBlock:nil otherBlock:^(UIAlertAction *action) {
[HSQSchema openURLSpmExtern:string];
}];
}
});
}
4.APNS回调
#pragma mark - iOS 10以下处理
/** APP已经接收到“远程”通知(推送) - 透传推送消息 */
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
// 处理APN,用来标识同时走APNS和透传消息时只处理APNS时
self.isAPNS = true;
// 跳转处理
[self dealwithAPNSMessage:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
}
#pragma mark - UNUserNotificationCenterDelegate iOS 10以上(包括iOS 10)处理
//App在后台运行及程序退出杀死 会调用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
{
// 处理APN,用来标识同时走APNS和透传消息时只处理APNS时
self.isAPNS = YES;
// 远程推送消息
if ([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSDictionary *userInfo = response.notification.request.content.userInfo;
// 跳转处理
[self dealwithAPNSMessage:userInfo];
}
completionHandler();
}