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

不同版本極光推送SDK集成各有差異,集成時一定要注意版本號,樓主已將博文更新成最新的SDK JPush v3.0.2. 各位童鞋先閱讀下JPush v3.0.2的升級指南吧!
極光的最近更新
極光資源下載

JPush SDK v3.0.2 升級指南
  • 更新時間
    2017-02-13

  • 更新信息
    修復:DNS解析失敗帶來的崩潰問題,提升穩定性

  • 升級提示
    建議升級!
    注意:支持 Xcode 8.0 以上版本 開啟 bitcode。

  • 升級指南
    1.注意 3.0.0及以上版本將不再支持處理器為i386的模擬器。
    2.添加libresolv.tbd庫(2.2.0及以上版本要求)
    3.Xcode7 升級到 Xcode8,替換原先導入的 .dylib 框架為 .tbd (特別留意)

本博文修改歷史
  • 2017.03.25 ------------ JPush v3.0.2
  • 2016.12.13 ------------ JPush v2.2.0
  • 2016.09.28 ----------- JPush v2.1.9

簡介

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

注意:極光的遠程推送是免費的,并同時兼顧iOS,Android,Windows Phone三個平臺,但相應的用戶統計,終端統計等功能是不免費的。如果你需要用戶統計,終端統計這些功能意味著需要付費才能使用。

參考鏈接

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

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

集成步驟

  1. 遠程推送原理
  2. Xcode8創建項目,配置自動創建App ID/證書/配置文件
  3. 創建APNs 推送證書
  4. 在極光推送后臺創建應用,并上傳APNs 推送證書
  5. 項目中集成極光推送SDK
  6. notification payload 和遠程推送類型
  7. 獲取 APNs推送內容
  8. 極光推送后臺發送遠程推送測試
1. 遠程推送原理

當iOS設備連網的情況下,iOS設備和蘋果服務器建立了一個長鏈接,即便應用處于掛起和后臺的狀態,蘋果可以給iOS設備中的應用發送通知。


遠程推送原理
概念
  1. iOS:iOS設備
  1. APNs Server:蘋果服務器
  2. Your App: 自己的應用
  3. Your Server:自己的服務器
推送流程
  1. iOS 應用注冊推送通知,iOS設備將設備的UDID和應用的Bundle ID發送到蘋果服務器。
  2. 蘋果服務器將接收到的UDIDBundle ID加密生成一個deviceToken,并返回給對應iOS應用。
  3. iOS應用將接收到的deviceToken發送到自己的服務器,服務器并保存。
  4. 自己的服務器需配置APNs 推送證書,當需要推送時,去后臺查詢推送目標設備的deviceToken,將notification payloaddeviceToken一起發送給蘋果服務器。notification payload是一個JSON字典,包含著發給應用程序的數據,并且包含通知的類型(類型決定系統如何通知用戶)。
  5. 蘋果服務器通過deviceToken找到對應設備下的對應應用,推送消息。
說明
  1. 真機測試并且包含推送功能需要創建對應App ID/證書/配置文件, 這步可以用Xcode8 自動創建,而不需要到蘋果開發者平臺去創建。如果不是Xcode8,則需要去開發者平臺申請,確保App ID包含推送通知服務,并且在Xcode中配置,保證真機測試即可。
  2. 我們自己的服務器需要配置 APNs 推送證書,同樣的分為開發證書和生產證書。需要到蘋果開發者平臺去申請。
  3. 如果不借助第三方推送平臺,我們需要完成推送流程中的1,3,4步。借助極光推送,那么我們只需要完成推送流程中的1,3步,但同樣需要我們完成第4步中的申請APNs 推送證書,并且上傳到極光推送平臺。
2. Xcode8配置自動創建App ID/證書/配置文件
  1. 在Xcode8下,確保已經登錄付費蘋果開發者帳號。請開啟Application Target的Capabilities->Push Notifications選項。
開啟遠程推送

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

勾選自動管理

3.檢查Xcode自動創建的App ID證書配置文件,保證下圖中第4步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 推送證書
  1. 核對應用的Bundle ID 等信息是否正確.
    核對Bundle ID 等信息
5. 項目中集成極光推送SDK

極光推送最新版本3.0.2已支持CocoaPods導入。

  • 方式一:CocoaPods導入,一句話搞定。
pod 'JPush', '3.0.2'
  • 方式二:手動導入SDK和系統依賴庫
    jpush-ios-3.0.2.a
    jcore-ios-1.1.1.a
    JPUSHService.h
    
導入系統依賴庫

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及以上)
libresolv.tbd (JPush 2.2.0及以上版本需要)

3. AppDelegate.m 配置
導入以下頭文件

import "JPUSHService.h"

// 如果需要使用idfa功能所需要引入的頭文件(可選)

import <AdSupport/AdSupport.h>

ifdef NSFoundationVersionNumber_iOS_9_x_Max

import <UserNotifications/UserNotifications.h>

endif

并且遵守`<JPUSHRegisterDelegate>`協議

@interface AppDelegate ()<JPUSHRegisterDelegate>
@end

注冊遠程推送,初始化極光推送SDK。

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{

//-------------注冊遠程推送
//notice: 3.0.0及以后版本注冊可以這樣寫,也可以繼續用之前的注冊方式
JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound;
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
//-------------極光推送SDK初始化
BOOL isProduction = NO;// NO為開發環境,YES為生產環境
//廣告標識符 如果沒有使用IDFA直接傳nil
NSString *advertisingId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
[JPUSHService setupWithOption:launchOptions appKey:@"極光推送AppKey"
channel:nil
apsForProduction:isProduction
advertisingIdentifier:advertisingId];
return YES;
}

以上是注冊遠程推送極光版本,很簡潔。下面是注冊遠程推送系統版本,可以參考下。

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue];  
  
if (version >= 10.0)  
{  
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];  
    [center requestAuthorizationWithOptions:UNAuthorizationOptionCarPlay | UNAuthorizationOptionSound | UNAuthorizationOptionBadge | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {  
          
        if (granted) {  
            NSLog(@" iOS 10 request notification success");  
        }else{  
            NSLog(@" iOS 10 request notification fail");  
        }  
    }];  
}  
else if (version >= 8.0)  
{  
    UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert categories:nil];  
    [application registerUserNotificationSettings:setting];  
}else  
{     //iOS <= 7.0
    UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;  
    [application registerForRemoteNotificationTypes:type];  
}    

//注冊通知  
[[UIApplication sharedApplication] registerForRemoteNotifications];  
  
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.notification payload 和遠程推送類型
發送遠程推送的服務器發送給APNs的每個通知都包含payload。 payload是一個JSON字典,包含要發送到應用程序的任何自定義數據,并包含有關推送類型的信息(推送類型決定系統如何通知用戶)。

遠程推送分為普通推送,后臺推送,靜默推送三種方式。以下以遠程推送的類型來討論下payload的構造。以下只考慮iOS7之后的操作系統。

- 普通推送 
  - payload 構造:包含聲音、內容、角標、自定義字段。

{
aps = {
alert = "顯示內容";//alert對應的值也可以是字典,字典中body鍵的值對應顯示內容
badge = 1; // App 角標,可推送 n、+n、-n 來實現角標的固定、增加、減少
sound = default; // 推送聲音,默認系統三全音,如需使用自己的聲音,需要將聲音文件拖拽&拷貝至 Xcode 工程目錄任意位置,并在推送時指定其文件名
};
proNo = "tb_pro_no_id249349874"; // 自定義字段
DesVc = "ProViewController";
}


 - 處于未啟動,系統會顯示通知,點擊通知橫幅啟動,在以下方法中獲取通知內容:

-(BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

 - 處于后臺,系統會顯示通知,但不會通知對應應用(即應用的方法不會被調用)。
 - 處于前臺,iOS10之后會顯示通知。(iOS10之前會不會展示通知,樓主也記不住了??)在以下方法中獲取通知內容:
   - iOS7 ~ iOS9

-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler

   - iOS10 after (UNUserNotificationCenterDelegate中的代理方法)

-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler

 
- 后臺推送
 - 必須在 Xcode 工程中 TARGETS – Capabilities – Background Modes 中開啟Remote notifications功能。
 - payload構造:必須攜帶 "content-available" = 1,必須攜帶 alert中的顯示信息、badge、sound 中 至少 1 個字段。

{
aps = {
alert = "顯示內容";//alert對應的值也可以是字典,字典中body鍵的值對應顯示內容
badge = 1;
"content-available" = 1; // 必帶字段
sound = default;
};
key1 = value1;
}

 - 處于未啟動,同上述普通推送一致。
 - 處于后臺或者掛起,系統會顯示通知。通過下述獲取通知內容,你的應用會在后臺啟動(如果應用為掛起狀態,則喚醒它,處于后臺狀態),將有30秒的時間進行處理通知或者下載數據等操作。

-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler


 - 處于前臺, 系統會顯示通知。可通過以下方法獲取內容:

   - iOS7 after

-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler

   - 注:iOS10 之后除了會調用上面的方法,還會調用此方法 (UNUserNotificationCenterDelegate中的代理方法)

-(void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler


- 靜默推送
 - 系統不會顯示通知,用戶不會有任何察覺。
 - payload構造:必須攜帶 "content-available" = 1。必須不攜帶 alert中的顯示內容、badge、sound。

{
aps = {
alert = "";//alert對應的值也可以為字典,字典中不能包含body鍵值對。
"content-available" = 1; // 必帶字段
};
key1 = value1;
}

 - 處于未啟動,獲取不到通知內容
 - 處于后臺,iOS7 之后你的應用會在后臺啟動(如果應用為掛起狀態,則喚醒它,處于后臺狀態),將有30秒的時間進行處理通知或者下載數據等操作。可通過下述方法獲取內容:

-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler

 - 處于前臺, iOS7 之后可通過下述方法獲取內容:

-(void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void(^(UIBackgroundFetchResult))completionHandler



#####7.獲取 APNs(通知) 推送內容
iOS 設備收到一條推送(APNs),用戶點擊推送通知打開應用時,應用程序根據狀態不同進行處理,需在 AppDelegate 中的以下方法中添加代碼以獲取apn內容。
- 如果 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.此方法會在以下幾種情況下調用
 - iOS7 ~ iOS9 前臺接收普通推送。
 - iOS7之后開啟Background Mode 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

//前臺收到推送,可以采取必要的措施處理通知和更新APP的內容。
-(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三種類型可以設置
// 如果不需提醒可傳UNNotificationPresentationOptionNone
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

#####8. 極光推送后臺發送遠程推送測試
1.登錄`極光推送`,切換到控制臺,并點擊對應的應用,點擊推送按鈕
![點擊推送按鈕](http://upload-images.jianshu.io/upload_images/790038-ce63654e0f2dafec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![點擊發送通知](http://upload-images.jianshu.io/upload_images/790038-e67a3d8e1f5eec8e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

2.設置推送內容
![設置推送內容](http://upload-images.jianshu.io/upload_images/790038-86e85fb6524a99e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

選擇推送環境iOS開發環境,目標人群,發送時間。再點擊可選設置設置消息的具體內容。
![選擇推送環境](http://upload-images.jianshu.io/upload_images/790038-b8d4bb9b0e23c641.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


3.設置消息具體內容。

![設置推送內容](http://upload-images.jianshu.io/upload_images/790038-f8e05e4ad5093b25.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


4.iOS設備接收到遠程推送
![iOS設備接收到遠程推送](http://upload-images.jianshu.io/upload_images/790038-9969a3408695827e.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
以下為打印的通知內容。

{
"_j_msgid" = 3017423712;
aps = {
alert = {
body = "你愛談天,我愛笑~~";
subtitle = "每天堅持1小時,會有大收獲。";
title = "天天";
};
badge = 100;
sound = default;
};
}



5.推送歷史可以在這里看得到,但有延遲,可能遠程推送已接收到,推送歷史數據還沒有更新到最新。
![推送歷史](http://upload-images.jianshu.io/upload_images/790038-994708e85592d06b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


關于Xcode8下集成極光遠程推送的簡單介紹,到這里就結束了。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容