iOS極光推送封裝

weixin_33850890發表於2016-04-12

通常來說專案中的推送功能一般是使用第三方來實現,可以極大的降低開發時間及成本,下面就簡單介紹下關於極光推送的一個簡易封裝使用

整合步驟及使用注意點

/*  遠端推送整合指南 (使用極光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];
}

相關文章