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

上周,完成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 <UserNotifications/UserNotifications.h>
#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];


以上就是对于极光推送的简单介绍,如有问题欢迎指出或留言。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容