Xcode8下快速集成極光推送併兼顧iOS10

前言

iOS10下,遠程推送發生了變化,新增的UserNotifications.framework將本地推送和遠程推送整合在一塊兒。 最近剛剛更新了Xcode8,自動建立證書和配置文件確實方便許多。琰君分享下以開發環境爲例(非生產環境)在Xcode8下,快速集成極光推送併兼顧iOS10。ios

注意:極光推送的遠程推送是免費的,但相應的用戶統計,終端統計等功能是難免費。若是你須要用戶統計,終端統計這些功能意味着須要付費才能使用。服務器

參考連接

開發證書配置
APNs 推送原理及問題
iOS 推送全解析,你不可不知的全部 Tips!app

接下來假設你都瞭解證書相關的,推送的一些概念和極光推送的知識。那麼相信你應該知道須要一臺iOS設備和一個蘋果開發者賬號才能去體驗遠程推送。若是你清楚遠程推送的原理,那能夠直接從如下第2步開始。函數

集成步驟

  1. 遠程推送原理
  2. Xcode8建立項目,配置自動建立App ID/證書/配置文件
  3. 建立APNs 推送證書
  4. 在極光推送後臺建立應用,並上傳APNs 推送證書
  5. 項目中集成極光推送SDK
  6. 獲取 APNs(通知) 推送內容
  7. 極光推送後臺發送遠程推送測試

1. 遠程推送原理測試

當iOS設備聯網的狀況下,蘋果服務器和iOS設備創建了一個長連接,即使應用處於掛起和後臺的狀態,蘋果能夠給iOS設備中的應用發送通知。fetch

遠程推送原理網站

概念ui

  1. iOS:iOS設備
  2. APNS Server:蘋果服務器
  3. Your App: 本身的應用,例如咕咚
  4. Your Server:本身的服務器,例如咕咚服務器

推送流程加密

  1. iOS 應用註冊推送通知,iOS設備將設備的UDID和應用的Bundle ID到蘋果服務器。
  2. 蘋果服務器將接收到的UDIDBundle ID加密生成一個deviceToken,並返回給對應iOS應用。
  3. iOS應用將接收到的deviceToken發送到本身的服務器,服務器並保存。
  4. 本身的服務器需配置APNs 推送證書,當須要推送時,去後臺查詢推送目標設備的deviceToken,將消息和deviceToken一塊兒發送給蘋果服務器。
  5. 蘋果服務器經過deviceToken找到對應設備下的對應應用,推送消息。

說明spa

  1. 咱們的應用真機測試須要建立對應App ID/證書/配置文件, 這步能夠用Xcode8 自動建立,而不須要到蘋果開發者平臺去建立。若是不是Xcode8,則須要去開發者平臺申請,而且在Xcode配置,保證真機測試便可。
  2. 咱們本身的服務器須要配置 APNs 推送證書,一樣的分爲開發證書和生產證書。須要到蘋果開發者平臺去申請。
  3. 若是不借助第三方推送平臺,咱們須要完成推送流程中的1,3,4步。藉助極光推送,那麼咱們只須要完成推送流程中的1,3步,但一樣須要咱們申請APNs 推送證書,而且上傳到極光推送平臺。

2. Xcode8配置自動建立App ID/證書/配置文件

  1. 在Xcode8下,確保已經登陸付費蘋果開發者賬號。請開啓Application Target的Capabilities->Push Notifications選項。

開啓遠程推送

2.勾選自動管理App ID證書配置文件

勾選自動管理

3.檢查Xcode生產的App ID證書配置文件這步配置好了就能夠真機運行了。

檢查Xcode生產的App ID/證書/配置文件

3. 建立APNs 推送證書

  1. 登陸開發者網站,並點擊按鈕建立證書

點擊按鈕建立證書

2.選擇開發環境APNs 推送證書點擊右下角按鈕建立

建立開發環境APNs 推送證書

3.選擇工程的App ID

選擇工程的App ID

4.上傳證書請求文件,不知道的童鞋可參照開發證書配置

上傳證書請求文件

5.點擊下載證書,並雙擊安裝到鑰匙串.

安裝APNs 推送證書

6.打開鑰匙串,並參照下圖指示,找到對應的APNs 推送證書,並選擇右鍵導出.

鑰匙串導出證書

7.設置證書名字,並選擇證書存放位置。

設置證書名字

8.設置證書密碼,可不填。極光推送支持證書設置密碼,但像leanCloud推送不支持證書設置密碼,各位童鞋可按照實際狀況來。最後輸入電腦開密碼,導出證書。

設置證書密碼

輸入電腦開機密碼導出證書

4. 在極光推送後臺建立應用,並上傳APNs 推送證書

1.登陸極光推送平臺,切換到控制檯,並建立應用。接下來在應用信息中上傳開發APNs 推送證書生產環境APNs 推送證書配置相似,不作贅述.

上傳開發APNs 推送證書

  1. 覈對應用的Bundle ID 等信息是否正確.

    覈對Bundle ID 等信息

5. 項目中集成極光推送SDK

  1. 導入極光推送SDK
    jpush-ios-2.1.9.a
    JPUSHService.h
  2. 導入系統依賴庫
    CFNetwork.framework
    CoreFoundation.framework
    CoreTelephony.framework
    SystemConfiguration.framework
    CoreGraphics.framework
    Foundation.framework
    UIKit.framework
    Security.framework
    libz.tbd
    Adsupport.framework (獲取IDFA須要;若是不使用IDFA,請不要添加)
    UserNotifications.framework(Xcode8及以上)
  3. AppDelegate.m 配置
    導入如下頭文件

    #import "JPUSHService.h"
    #import <AdSupport/AdSupport.h>
    #ifdef NSFoundationVersionNumber_iOS_9_x_Max
    #import <UserNotifications/UserNotifications.h>
    #endif

    而且遵照<JPUSHRegisterDelegate>協議

    @interface AppDelegate ()<JPUSHRegisterDelegate>
    @end

    註冊遠程推送

    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    
     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爲生產環境
     //廣告標識符
     NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
     //Required(2.1.5版本的SDK新增的註冊方法,改爲可上報IDFA,若是沒有使用IDFA直接傳nil
     [JPUSHService setupWithOption:launchOptions appKey:@"極光推送AppKey"
                           channel:nil
                  apsForProduction:isProduction
             advertisingIdentifier:advertisingId];
     return YES;
    }

    獲得蘋果服務器返回的deviceToken,上傳到極光推送服務器。

    -(void)application:(UIApplication *)application
     didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    [JPUSHService registerDeviceToken:deviceToken];
    }

    註冊遠程通知失敗,好比沒有聯網的狀態下。

    -(void)application:(UIApplication *)application
     didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error);
    }

    6.獲取 APNs(通知) 推送內容

    iOS 設備收到一條推送(APNs),用戶點擊推送通知打開應用時,應用程序根據狀態不一樣進行處理需在 AppDelegate 中的如下方法中添加代碼以獲取apn內容
    1.若是 App 狀態爲未運行,此函數將被調用,若是launchOptions包含UIApplicationLaunchOptionsRemoteNotificationKey表示用戶點擊apn 通知致使app被啓動運行;若是不含有對應鍵值則表示 App 不是因點擊apn而被啓動,可能爲直接點擊icon被啓動或其餘。

    -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    // apn 內容獲取:
    NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey]
    }

    2.基於iOS 6 及如下的系統版本,若是 App狀態爲正在前臺或者點擊通知欄的通知消息,那麼此函數將被調用,而且可經過AppDelegate的applicationState是否爲UIApplicationStateActive判斷程序是否在前臺運行。

    -(void)application:(UIApplication *)application 
    didReceiveRemoteNotification:(NSDictionary *)userInfo{
    }

    3.基於iOS 7 及以上的系統版本,若是是使用 iOS 7 的 Remote Notification 特性那麼此函數將被調用

    -(void)application:(UIApplication *)application
     didReceiveRemoteNotification:(NSDictionary *)userInfo
           fetchCompletionHandler:
               (void (^)(UIBackgroundFetchResult))completionHandler {
    [JPUSHService handleRemoteNotification:userInfo];
    NSLog(@"iOS7及以上系統,收到通知:%@", [self logDic:userInfo]);
    
    completionHandler(UIBackgroundFetchResultNewData);
    }
    -(NSString *)logDic:(NSDictionary *)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;
    }

    4.基於iOS 10及以上的系統版本,
    [application: didReceiveRemoteNotification:]將會被系統廢棄,
    由新增UserNotifications.framework中的如下兩個方法替代。

    [UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:]
    [UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]

在極光推送SDK2.1.9版本之後可實現SDK封裝的JPUSHRegisterDelegate協議方法,適配iOS10新增的delegate協議方法。
即如下兩個方法:

#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; // 收到推送的消息內容
  NSNumber *badge = content.badge;  // 推送消息的角標
  NSString *body = content.body;    // 推送消息體
  UNNotificationSound *sound = content.sound;  // 推送消息的聲音
  NSString *subtitle = content.subtitle;  // 推送消息的副標題
  NSString *title = content.title;  // 推送消息的標題

 if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
    NSLog(@"iOS10 前臺收到遠程通知:%@", [self logDic: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;
  UNNotificationRequest *request = response.notification.request; // 收到推送的請求
  UNNotificationContent *content = request.content; // 收到推送的消息內容
  NSNumber *badge = content.badge;  // 推送消息的角標
  NSString *body = content.body;    // 推送消息體
  UNNotificationSound *sound = content.sound;  // 推送消息的聲音
  NSString *subtitle = content.subtitle;  // 推送消息的副標題
  NSString *title = content.title;  // 推送消息的標題
 if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    [JPUSHService handleRemoteNotification:userInfo];
    NSLog(@"iOS10 收到遠程通知:%@", [self logDic:userInfo]);
  }
completionHandler();  // 系統要求執行這個方法
}
#endif

7. 極光推送後臺發送遠程推送測試

1.登陸極光推送,切換到控制檯,並點擊對應的應用,點擊推送按鈕

點擊推送按鈕

點擊發送通知

2.設置推送內容

設置推送內容


選擇推送環境iOS開發環境,目標人羣,發送時間。再點擊可選設置設置消息的具體內容。

屏幕快照

3.設置消息具體內容。遠程推送分爲普通推送/後臺推送/靜默推送3種類型,而且類型由推送消息設置來決定。關於如何設置請參考iOS 推送全解析,你不可不知的全部 Tips!

屏幕快照 2016-09-26 上午10.54.59.png

4.iOS設備接收到遠程推送

接收到遠程推送

5.推送歷史能夠在這裏看獲得,但有延遲,可能遠程推送已接收到,推送歷史數據尚未更新到最新。

屏幕快照 2016-09-28 上午10.23.16.png

關於Xcode8下集成極光遠程推送的簡單介紹,到這裏就結束了。


 

文/趙先生Try(簡書做者) 原文連接:http://www.jianshu.com/p/53e0244e6081 著做權歸做者全部,轉載請聯繫做者得到受權,並標註「簡書做者」。

相關文章
相關標籤/搜索