iOS极光推送封装

通常来说项目中的推送功能一般是使用第三方来实现,可以极大的降低开发时间及成本,下面就简单介绍下关于极光推送的一个简易封装使用

集成步骤及使用注意点

/*  远程推送集成指南 (使用极光SDK)
 
 1、准备生产、开发环境.p12文件  http://docs.jpush.io/client/ios_tutorials/#ios_1
 
 2、下载需要集成SDK    http://docs.jpush.io/resources/#sdk
 
 2.1 下载 JPush-iOS-SDK ,得到一个lib 和一个Demo,将lib 导入项目中;
 libz.tbd  ---》 注:Xcode7需要的是libz.tbd;Xcode7以下版本是libz.dylib
 2.2 同时创建并配置PushConfig.plist文件在 SDK目录下
 2.2 注册帐号:https://www.jpush.cn;
 2.3 添加应用名,上传对应环境的.p12文件;此步完成后得到一对字符串 AppKey 和 MasterSecret;
 
 3、在 AppDelegate.m 中复制如下代码:

------AppDelegate.m 的调用示例------------------------------------------------------------
 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
 
 //配置推送
 [ZQPushManager configurePushWithOptions:launchOptions];
 
 return YES;
 }
 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
 {
 [ZQPushManager registerDeviceToken:deviceToken];
 }
 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
 {
 [ZQPushManager handleRemoteNotification:userInfo];
 }
 -(void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
 {
 [ZQPushManager handleRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
 }
 
 - (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification
 {
 [ZQPushManager handleLocalNotificationForRemotePush:notification];
 }
 - (void)applicationWillEnterForeground:(UIApplication *)application {
 [ZQPushManager configurePushWithOptions:nil];
 }
 - (void)applicationWillResignActive:(UIApplication *)application {
 [ZQPushManager sharedManager].justInBack = YES;
 }
 ------AppDelegate.m 的调用完成---------------------------------------------------------- 

 4、打包给测试开发、生产环境,发布appstore配置;
    测试地址包:端口地址为测试环境,证书使用开发证书,测试手机直接连接电脑安装;
    正式地址包(避免线上正式用户收到):端口地址为正式环境,证书使用生产证书,测试手机用ad-hoc包安装;
    发布appstore:端口地址为正式,证书使用生产证书,发布;
 
 4.1 PushConfig.plist配置说明;
    APS_FOR_PRODUCTION (备用参数,暂时不需要配置):0表示开发证书,1表示生产证书;
    CHANNEL(不需要配置):在工程 - TARGETS - BuildSetting - SearchPaths - User Header Search Paths
            添加PushConfig.plist在工程中的相对路径(列如:$(SRCROOT)/plugIn/JPush/PushConfig.Plist,plugIn、JPush为文件夹))
    APP_KEY:配置为极光开发或者生产AppKey;
    
    注意:极光目前通过同一个账号来区分开发和生产环境,而我们后台是通过两个极光账号区别环境(测试账号对应极光开发环境,正式账号对应生产环境),极光并不通过账号来区分ios的环境。
 4.2 ZQPushManager.m里在clickRemoteNotification里配置app端口地址;
    

 5、细节注意:
     method_2 didReceiveLocalNotification
     method_1 didReceiveRemoteNotification:(NSDictionary *)userInfo
     fetchCompletionHandler:
     
     * 在iOS7.0之后,在前台收到远程通知,或者点击了后台的通知,都会调用method_1的方法 ,userInfo就是收到的通知,可根据需要做相应的处理;
     
     5.1 后台收到的远程通知,会自动下拉弹出,而前台收到时,不会弹出,需要单独处理,一般的做法有3种:
     5.1.1 转化成本地通知,丢到通知栏;
     5.1.2 转化成AlertView弹出;
     5.1.3 定义一个和系统通知一样的效果弹出; (PS:这个我还没实现 )
 
     5.2 判断用户是否允许通知;
     5.2 5.1.1转换成本地通知时,会调用一次method_2;点击通知栏的本地通知时会再调用一次,要做区分;
     5.3 未获得通知授权时候的跳转: @"prefs:root=NOTIFICATIONS_ID&path=com.365sji.iChanl";
     5.4 应用内注销远程通知;发送一条极光指定的通知 kJPFNetworkDidCloseNotification;
     5.5 开启和注销之间的快速转换:
     当用户前往5.2,就判断可能重新激活通知,此时在willEnterForground重新注册通知;
 
 */
  • 创建一个Nsobjct 的类 ( ZQLPushManager )

.h文件

#import <Foundation/Foundation.h>

@interface ZQLPushManager : NSObject

@property (nonatomic) BOOL justInBack;
@property (nonatomic) BOOL clickNotification;

+ (ZQLPushManager *)shareManager;

/// 配置推送
+ (void)configurePushWithOptions:(NSDictionary*)launchOptions;

///注册token
+ (void)registerDeviceToken:(NSData *)deviceToken;

/// 操作收到的远程消息
+ (void)handleRemoteNotification:(NSDictionary*)notification;

/// 远程消息操作完成
+ (void)handleRemoteNotification:(NSDictionary*)notification fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

///处理远程通知转化而来的本地通知
+ (void)handleLocalNotificationForRemotePush:(UILocalNotification*)notification;

/// 处理消息内容
+ (void)clickRemoteNotification:(NSDictionary*)notification;

///清理角标
+ (void)clearBadge;

///是否开启了允许通知
+ (BOOL)isOpenRemoteNotification;

///取消注册通知
+ (void)unregisterRemoteNotifications;

///允许/取消允许通知switch事件 on == 允许通知
+ (void)changeRemotePushState:(UISwitch*)sender;

@end

** .m文件**

#import "ZQLPushManager.h"
#import "JPUSHService.h"


@implementation ZQLPushManager

static ZQLPushManager* manager = nil;

+(ZQLPushManager *)shareManager
{
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        manager = [[ZQLPushManager alloc] init];
    });
    return manager;
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        
        self.justInBack = NO;
        self.clickNotification = NO;
    }
    return  self;
}

/// 配置推送
+ (void)configurePushWithOptions:(NSDictionary*)launchOptions
{
    if (![DataManager sharedManager].allowRemotePush){ // 如果用户不允许通知
        return;
    }else{
        // 注册
        [self registerRemoteNotification];
        
        [DataManager sharedManager].remotePushStateMaybeChange = NO;
    }
    
    // 初始化
    [JPUSHService setupWithOption:launchOptions];
    
    // 设置tag和标签
    //    [self setTagsAndAlias];
    
    // 如果通过点击推送通知启动应用
    if (launchOptions != nil) {
        NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (dictionary != nil) {
            [self clickRemoteNotification:dictionary];
            
            [self clearBadge];
        }
    }
}
/// 注册远程通知
+ (void)registerRemoteNotification
{
    // Required
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
        //可以添加自定义categories
        [JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
                                                       UIUserNotificationTypeSound |
                                                       UIUserNotificationTypeAlert)
                                           categories:nil];
    } else {
        //categories 必须为nil
        [JPUSHService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                       UIRemoteNotificationTypeSound |
                                                       UIRemoteNotificationTypeAlert)
                                           categories:nil];
    }
}
///在前台和状态栏收到远程消息
+(void)handleRemoteNotification:(NSDictionary*)notification fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
{
    [ZQLPushManager handleRemoteNotification:notification];
    
    //获取通知的标题和描述
    NSString* messageTitle = [[notification objectForKey:@"aps"]objectForKey:@"alert"];
    NSString* description = [notification objectForKey:@"videoDesc"];
    // 应用从后台点击消息进入
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive && ([ZQLPushManager shareManager].justInBack)){
        [ZQLPushManager clickRemoteNotification:notification];
        
    }else{ //正在通知栏或前台
        
        UILocalNotification *localNotification = [[UILocalNotification alloc] init];
        localNotification.userInfo = notification;
        localNotification.soundName = UILocalNotificationDefaultSoundName;
        localNotification.alertBody = description;
        [ZQLPushManager shareManager].clickNotification = NO;
        [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
        
        // 应用正在前台
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
#warning 后续自定义通知效果,仿原生;
            //  如果当前控制器不是视频播放控制器
            //  if (![DataManager sharedManager].isMovieDetailVC) {
            kSelfWeak;
            UIAlertView* alert = [UIAlertView alertViewWithTitle:messageTitle message:description cancelButtonTitle:@"取消" otherButtonTitles:@[@"前往"] onDismiss:^(NSInteger buttonIndex, NSString *buttonTitle) {
                if ([buttonTitle isEqualToString:@"前往"]) {
                    [weakSelf clickRemoteNotification:notification];
                }
            } onCancel:^{
                [weakSelf clearBadge];
            }];
            
            [alert show];
        }
        // }
    }
    completionHandler(UIBackgroundFetchResultNewData);
}
///处理远程通知转化而来的本地通知
+ (void)handleLocalNotificationForRemotePush:(UILocalNotification*)notification
{
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive&&[ZQLPushManager shareManager].justInBack)
    { // 如果用户点击通知进入
        [ZQLPushManager clickRemoteNotification:notification.userInfo];
    }
    [ZQLPushManager shareManager].clickNotification = YES;
}
/// 处理消息
+ (void)clickRemoteNotification:(NSDictionary*)notification
{
    [ZQLPushManager shareManager].justInBack = NO;
    [self clearBadge];
    
    NSString* videoType = [notification objectForKey:@"videoType"];
    NSString* videoTypeValue = [notification objectForKey:@"videoTypeValue"];
    
    UIViewController* destinationVC = nil;
    
    // 如果是通过messageId跳转
    if ([[NSString stringBySpaceTrim:videoTypeValue] isEqualToString:@""]) {
        
        NSString* messageId = [notification objectForKey:@"messageId"];
        NSString* contentStr = isTrueEnvironment ? @"view/messageDetails.html?newsId=" : @"daziboApp/view/messageDetails.html?newsId=";
        NSString* urlStr = [NSString stringWithFormat:@"%@://%@/%@%@",kHttpHead,kServerResourceHost, contentStr,messageId];
        NSLog(@"**************%@",urlStr);
        
//        destinationVC = [[XYWebVC alloc] initWithURLString:urlStr];
//        destinationVC.navigationItem.title = @"消息";
        
    }else if ([videoType isEqualToString:@"1"]) { //如果是视频ID
        //        destinationVC = [[MovieDetialVC alloc] initWithVideoId:videoTypeValue];
        
        
    }else if ([videoType isEqualToString:@"2"]){ //如果是视频网址
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:videoTypeValue]];
        //        destinationVC = [[XYWebVC alloc] initWithURLString:videoTypeValue];
    }else{
        return;
    }
    
    id rootVC = [[UIApplication sharedApplication] keyWindow].rootViewController;
    
    if ([rootVC isKindOfClass:[CLNavigationController class]]) {
        CLNavigationController * navc = (CLNavigationController *)rootVC;
        [navc pushViewController:destinationVC animated:YES];
    }else{
        [rootVC presentViewController:destinationVC animated:YES completion:^{
        }];
    }
}
///清除角标
+ (void)clearBadge
{
    [JPUSHService resetBadge];
    [UIApplication sharedApplication].applicationIconBadgeNumber = 1;
    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}
/// 设置tag和标签
+ (void)setTagsAndAlias
{
    [JPUSHService setAlias:@"159" callbackSelector:nil object:nil];
    [JPUSHService setTags:[NSSet set] callbackSelector:nil object:nil];
    [JPUSHService setTags:[NSSet set] alias:nil callbackSelector:nil target:nil];
}
+ (BOOL)isOpenRemoteNotification
{
    BOOL isOpenNotification;
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
        isOpenNotification = !([[UIApplication sharedApplication]currentUserNotificationSettings].types == 0) ;
        
    } else {
        isOpenNotification = !([[UIApplication sharedApplication]enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone);
    }
    return isOpenNotification;
}
+ (void)unregisterRemoteNotifications
{
    [[UIApplication sharedApplication] unregisterForRemoteNotifications];
    [[NSNotificationCenter defaultCenter] postNotificationName:kJPFNetworkDidCloseNotification object:nil];
}
+ (void)changeRemotePushState:(UISwitch*)sender
{
    if (!sender.on){ //关闭通知
        [ZQLPushManager unregisterRemoteNotifications];
    }else{ // 打开通知
        
        // 先检查用户在手机设置中是否打开了小自播通知
        
        // 如果未打开,提示用户打开
        if (![ZQLPushManager isOpenRemoteNotification]) {
            UIAlertView* alert = [UIAlertView alertViewWithTitle:@"提示" message:@"请在 设置 - 通知 中找到iChanl应用,\n勾选允许通知" cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] onDismiss:^(NSInteger buttonIndex, NSString *buttonTitle) {
                [DataManager sharedManager].remotePushStateMaybeChange = YES;
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=NOTIFICATIONS_ID&path=com.365sji.iChanl"]];
                
            } onCancel:^{
                sender.on = NO;
                [DataManager sharedManager].allowRemotePush = sender.on;
            }];
            [alert show];
            
        }else{ //如果已打开,马上注册推送通知
            [ZQLPushManager configurePushWithOptions:nil];
        }
        [DataManager sharedManager].allowRemotePush = sender.on;
    }
}

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

推荐阅读更多精彩内容