极光推送点击消息栏跳转到指定页面、设置标签或别名

上周,完成app新版本的开发。自从进入这版app的开发就没来更新过文章了,接下来会陆陆续续写一下在这过程中遇到的问题及一些总结。今天,就先说说消息推送吧。

推送,大家都不陌生,没有推送功能的app估计是少数。当然,对于推送介绍的文章也非常多也很仔细,但是真正开发过程中,还是会遇到各种问题,接下来会和大家谈谈集成推送的方法及我在开发中遇到的问题,但愿能给你们开发中遇到类似的问题时提供一种思路。

在推送过程我遇到的问题主要有:
1.在点击消息栏进入指定页面后,页面的点击事件不响应
2.点击消息栏进入指定页面后,页面的导航栏问题

其实这两个问题,归根结底是因为跳转时选择的控制器不对。比如当我点击消息栏时,希望跳转到A页面,A中没有导航栏。我开始用的是[self.window.rootViewController presentViewController:A animated:YES completion:nil],这时候跳转到A页面后,A页面中控件的点击事件不起作用了,后面发现,是因为层级图不对。而且用present的话,没有导航栏,所以当你跳转到指定页面A时,如果A页面的点击事件还有跳转到新页面B的功能,那么这个当你通过A push出来的B页面是没有导航栏的,而实际上我们希望的B是有导航栏的。

最后换成了pushViewController的方法。这个方法的关键是,你得找到当前的的VC,比如A页面是通过tabbar的第一个item中的VC的navpush出来的,那么这时候,只要找到tabbar第一个Item对应的nav中VC,然后用这个VC的 nav
push出A页面,问题就可以解决了。

接下来,说说该如何集成极光推送、如何处理收到通知时的页面跳转问题,以及如何设置标签和别名。

一、处理收到通知时页面跳转问题。
1.你需要到极光推送的平台上申请appkey,申请的过程中需要上传开发环境和正式环境的消息推送证书,所以如果你的app还没有消息推送证书,那么你需要到苹果的开发者账号中申请消息推送证书。如果对这个步骤不是很了解的话,可以参照iOS 证书 设置指南

2.申请好极光推送的appkey后,将下载的SDK拖到自己的工程中,添加相应的framework,配置好相关信息。也可参照官方文档
iOS SDK 集成指南

3.在 AppDelegate.m引入

#import "JPUSHService.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import 
#endif```
 
在` - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions`中注册极光推送
  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [self initRootViewController];

if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
    //iOS10以上
    JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
    entity.types = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
    [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
}else if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
    //iOS8以上可以添加自定义categories
    [JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
                                                      UIUserNotificationTypeSound |
                                                      UIUserNotificationTypeAlert)
                                          categories:nil];
}
else {
    //iOS8以下categories 必须为nil
    [JPUSHService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                      UIRemoteNotificationTypeSound |
                                                      UIRemoteNotificationTypeAlert)
                                          categories:nil];
}
BOOL isProduction = NO;// NO为开发环境,YES为生产环境

//Required(2.1.5版本的SDK新增的注册方法,改成可上报IDFA,如果没有使用IDFA直接传nil
[JPUSHService setupWithOption:launchOptions appKey:@"你的极光推送appkey"
                      channel:nil
             apsForProduction:isProduction
        advertisingIdentifier:nil];

//2.1.9版本新增获取registration id block接口。可以获取registrationID
[JPUSHService registrationIDCompletionHandler:^(int resCode, NSString *registrationID) {
    if(resCode == 0){
        NSLog(@"registrationID获取成功:%@",registrationID);
        
    }
    else{
        NSLog(@"registrationID获取失败,code:%d",resCode);
    }
}];


return YES;

}


注册deviceToken

pragma mark--注册devicetoken

  • (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [JPUSHService registerDeviceToken:deviceToken];
    }

收到通知时的处理 ,这里需要注意一下,iOS10收到通知时的方法和iOS10以前的不一样  
  • (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [JPUSHService handleRemoteNotification:userInfo];

    completionHandler(UIBackgroundFetchResultNewData);

    if (_application.applicationState == UIApplicationStateActive) {
    //程序运行时收到通知,先弹出消息框

      [self getPushMessageAtStateActive:userInfo];
    

    }

    else{
    //程序已经关闭或者在后台运行
    [self pushToViewControllerWhenClickPushMessageWith:userInfo];

    }

    [application setApplicationIconBadgeNumber:0];

    [JPUSHService handleRemoteNotification:userInfo];

    completionHandler(UIBackgroundFetchResultNewData);
    }

ifdef NSFoundationVersionNumber_iOS_9_x_Max

pragma mark- JPUSHRegisterDelegate

-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {

NSDictionary * userInfo = notification.request.content.userInfo;
UNNotificationRequest *request = notification.request; // 收到推送的请求
UNNotificationContent *content = request.content; // 收到推送的消息内容


if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
    
    
    if (_application.applicationState == UIApplicationStateActive) {
        //程序运行时收到通知,先弹出消息框
      
        [self getPushMessageAtStateActive:userInfo];
        
    }

    else{
     
        [self pushToViewControllerWhenClickPushMessageWith:userInfo];
    }
    
}
// 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);

}
//
-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary * userInfo = response.notification.request.content.userInfo;
[[NSUserDefaults standardUserDefaults] setObject:@"Inactive" forKey:@"applicationState"];

if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
    
    
    if (_application.applicationState == UIApplicationStateActive) {
        //程序运行时收到通知,先弹出消息框
        [self getPushMessageAtStateActive:userInfo];
        
        [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationState" object:@"0"];
        
    }
    
    else{
        
        [self pushToViewControllerWhenClickPushMessageWith:userInfo];
    }
    
}
completionHandler();  // 系统要求执行这个方法

}

endif

如果在程序运行时收到通知,这时消息栏不会显示通知,所以如果想让用户收到通知的话,应该是给用户一个弹框提醒,告诉用户有消息通知,当用户点击提示框中的确认查看按钮时,跳转到指定的页面

pragma mark -- 程序运行时收到通知

-(void)getPushMessageAtStateActive:(NSDictionary *)pushMessageDic{

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@""
                                                                             message:[[pushMessageDic objectForKey:@"aps"]objectForKey:@"alert"]
                                                                      preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"查看"
                                                          style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                                                              
                                                              [self pushToViewControllerWhenClickPushMessageWith:pushMessageDic];
                                                          }];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                           style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
                                                               
                                                           }];

    [alertController addAction:confirmAction];
    [alertController addAction:cancelAction];
    [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];

}

跳转到指定页面的方法。跳转到指定页面的话,可能会需要某些参数,这时可以根后台商定,根据参数跳转到相应的页面,同时也让后台把你需要的参数返回来。比如我和后台商定根据“pageType”这个参数确定跳转的页面。如果是跳转到次级页面,这里重要的是要找到正确的viewcontroller,用controller的nav进行push新页面。比如我的DetailViewController是用tabar的第一个item中的FirstViewController的nav进行push出来的,那么,当我点击通知消息想到跳转到DetailViewController,只要找到FirstViewController就可以了。

-(void)pushToViewControllerWhenClickPushMessageWith:(NSDictionary*)msgDic{

NSUserDefaults*pushJudge = [NSUserDefaults standardUserDefaults];

        if ([[msgDic objectForKey:@"pageType"] integerValue]==0){

// 跳转到第一个tabbarItem,这时直接设置 UITabBarController的selectedIndex属性就可以

         self.tabController.selectedIndex = 0;
            
        }else if ([[msgDic objectForKey:@"pageType"] integerValue]==1){
            
            //跳转到第二个tabbarItem
      
            self.tabController.selectedIndex = 1;
          
            
        }else if ([[msgDic objectForKey:@"pageType"] integerValue]==2){
            //跳转到第三个tabbarItem
            

            self.tabController.selectedIndex = 2;
            
        }else if ([[msgDic objectForKey:@"pageType"] integerValue]==3){
            //详情,这是从跳转到第一个tabbarItem跳转过去的,所以我们可以先让tabController.selectedIndex =0;然后找到VC的nav。
            
            self.tabController.selectedIndex =0;
            DetailViewController * VC = [[DetailViewController alloc]init];
            [VC setHidesBottomBarWhenPushed:YES];
        //因为我用了三方全屏侧滑手势,所以要找的是第一个tabbarController中的viewController的JTNavigationController ,接着再找JTNavigationController 里面的jt_viewControllers.lastObject,这样就可以找到FirstViewController了,然后跳转的时候就和正常的跳转一样了
            JTNavigationController *nav=(JTNavigationController *)self.tabController.viewControllers[0];
            UIViewController *vc=(UIViewController*)nav.jt_viewControllers.lastObject;
            
            [vc.navigationController pushViewController:VC animated:NO];
            
        }else {

        }

}


二、如何设置标签或者别名
消息推送,有时候只想推送给指定的人或者指定的版本,那么这时候我们就需要对设备设置标签或者别名了,这样推送的时候可以根据标签或者别名推送给指定的用户

  • (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    //标签
    __autoreleasing NSMutableSet *tags = [NSMutableSet set];
    //设置了IOS_ALL的标签,当推送时选了IOS_ALL这标签,那么只要装了这个app并且允许消息推送的用户就都能收到通知
    [self setTags:&tags addTag:@"IOS_ALL"];

    NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
    //根据版本号设置了IOSXX的标签,当推送时选了IOS2.1这标签,那么只要装了这个app并且允许消息推送的2.1版本的用户就都能收到通知

    [self setTags:&tags addTag:[NSString stringWithFormat:@"IOS%@",version]];

    if (_isLogin==YES) {
    //根据版本号设置了LoginUesr的标签,当推送时选了LoginUesr这标签,那么只要装了这个app并且允许消息推送的所有登录用户就都能收到通知
    [self setTags:&tags addTag:@"LoginUesr"];
    }else{

    }

    //别名,根据用户的UID去设置别名,那么可以指定的推送给某些用户
    __autoreleasing NSString *alias ;

    if (_userUID!= nil) {
    alias =[NSString stringWithFormat:@"%@",_userUID];

}
[self analyseInput:&alias tags:&tags];

[JPUSHService setTags:tags alias:alias callbackSelector:@selector(tagsAliasCallback:tags:alias:) object:self];

}

  • (void)tagsAliasCallback:(int)iResCode
    tags:(NSSet *)tags
    alias:(NSString *)alias {
    NSString *callbackString =
    [NSString stringWithFormat:@"%d, \ntags: %@, \nalias: %@\n", iResCode,
    [self logSet:tags], alias];

    NSLog(@"TagsAlias回调:%@", callbackString);
    }

  • (NSString *)logSet:(NSSet *)dic {
    if (![dic count]) {
    return nil;
    }
    NSString *tempStr1 =
    [[dic description] stringByReplacingOccurrencesOfString:@"\u"
    withString:@"\U"];
    NSString *tempStr2 =
    [tempStr1 stringByReplacingOccurrencesOfString:@""" withString:@"\""];
    NSString *tempStr3 =
    [[@""" stringByAppendingString:tempStr2] stringByAppendingString:@"""];
    NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding];
    NSString *str =
    [NSPropertyListSerialization propertyListFromData:tempData
    mutabilityOption:NSPropertyListImmutable
    format:NULL
    errorDescription:NULL];
    return str;
    }

pragma mark--设置推送的标签及别名

  • (void)setTags:(NSMutableSet **)tags addTag:(NSString *)tag {

    [*tags addObject:tag];
    }

  • (void)analyseInput:(NSString **)alias tags:(NSSet *)tags {
    // alias analyse
    if (![
    alias length]) {
    // ignore alias
    alias = nil;
    }
    // tags analyse
    if (![
    tags count]) {
    tags = nil;
    } else {
    __block int emptyStringCount = 0;
    [
    tags enumerateObjectsUsingBlock:^(NSString *tag, BOOL *stop) {
    if ([tag isEqualToString:@""]) {
    emptyStringCount++;
    } else {
    emptyStringCount = 0;
    stop = YES;
    }
    }];
    if (emptyStringCount == [
    tags count]) {
    *tags = nil;
    }
    }
    }

当用户退出登录的时候可以重置别名,不然设备还是会收到通知

[JPUSHService setAlias:@"" callbackSelector:@selector(tagsAliasCallback:tags:alias:) object:self];


以上就是对于极光推送的简单介绍,如有问题欢迎指出或留言。

你可能感兴趣的:(极光推送点击消息栏跳转到指定页面、设置标签或别名)