ios 極光推送的集成及注意事項

好涼一個秋

好久沒有發(fā)動態(tài)了,今天介紹一下極光推送,關(guān)于apple通知的一些原理,這里就不做細致的介紹了,想要了解內(nèi)部推送的原理,大家可以在簡書搜索iOS開發(fā)知識匯總專題,點擊鏈接http://www.itdecent.cn/collection/b9235769faa3 可直接進入,或者搜索微信公眾號iOS開發(fā)知識匯總

Snip20161024_2.png

now,我們從創(chuàng)建好極光應(yīng)用開始,獲得appkey之后,打開xcode,進入項目,如圖,可以看到有個開關(guān),push notifications

通知開關(guān)

打開開關(guān)之后,會生成一個項目名.entitlements的文件
entitlements.png

but在這之前,很多人沒有push notificaitons開關(guān),don't worry,進入極光主頁,你會發(fā)現(xiàn),需要導(dǎo)入各種依賴庫

依賴庫.png

我們在xcode下的Build Phases逐個添加依賴庫,如圖

Build Phases

導(dǎo)入依賴庫之后,在這里最關(guān)鍵的依賴庫是UserNotificationcations.framework(xcode8及以上),關(guān)閉程序,重新啟動,開關(guān)就會出現(xiàn),然后打開開關(guān),如圖

Push Notifications

在開關(guān)下面,steps有兩個項目,第一個如果爆紅,說明沒有導(dǎo)入項目所需的證書及配置文件(即在apple developer 生成的證書及配置文件) ,導(dǎo)入即可;如果第二個爆紅,可能是因為你不小心刪除了項目名.entitlements文件,解決方法是,關(guān)閉push Notifications開關(guān)之后再打開即可生成,如果不行的話,關(guān)閉程序,在關(guān)閉打開開關(guān)即可,如果 如果再不行,去你的廢紙簍里面找被你刪除的項目名.entitlements文件,重新拖到項目中重啟項目即可

Build Settings
如果你的工程需要支持小于7.0的iOS系統(tǒng),請到Build Settings 關(guān)閉 bitCode 選項,否則將無法正常編譯通過。
設(shè)置 Search Paths 下的 User Header Search Paths 和 Library Search Paths,比如SDK文件夾(默認為lib)與工程文件在同一級目錄下,則都設(shè)置為"$(SRCROOT)/{靜態(tài)庫所在文件夾名稱}"即可 。《來自極光文檔》

2.允許Xcode7支持Http傳輸方法

如果您使用的是2.1.9及以上的版本則不需要配置此步驟
如果用的是Xcode7或更新版本,需要在App項目的plist手動配置下key和值以支持http傳輸:
選擇1:根據(jù)域名配置
在項目的info.plist中添加一個Key:NSAppTransportSecurity,類型為字典類型。
然后給它添加一個NSExceptionDomains,類型為字典類型;
把需要的支持的域添加給NSExceptionDomains。其中jpush.cn作為Key,類型為字典類型。
每個域下面需要設(shè)置2個屬性:NSIncludesSubdomains、NSExceptionAllowsInsecureHTTPLoads。 兩個屬性均為Boolean類型,值分別為YES、YES?!秮碜詷O光文檔》 。如圖

Snip20161024_10.png

配置完以上之后,進入項目的appdelegate里面,首先導(dǎo)入頭文件和遵循代理

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

@interface AppDelegate ()<JPUSHRegisterDelegate>

在系統(tǒng)方法里面申請通知權(quán)限,這里最高只適用到xcode8.1(iOS10.1.2),以后如果出現(xiàn)iOS11在做更新改變

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
   if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
        entity.types = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
        [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
    }
    else 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];
    }
[JPUSHService setupWithOption:launchOptions appKey:appKey
                          channel:channel
                 apsForProduction:isProduction
            advertisingIdentifier:nil];  // 這里是沒有advertisingIdentifier的情況,有的話,大家在自行添加
    //注冊遠端消息通知獲取device token
    [application registerForRemoteNotifications];
}

注意:appkey一定不要忘了從極光復(fù)制過來

獲取deviceToken

// 獲取deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    [JPUSHService registerDeviceToken:deviceToken];
}
// 注意 :此方法在ios 3 以后可以使用,但是在很多朋友可能會遇到不調(diào)用此方法的情況,也就無法獲取deviceToke,這里提供一種解決方案
-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
    [application registerForRemoteNotifications];
}    
關(guān)于這個deviceToken,iOS10系統(tǒng)上,每次卸載重裝將產(chǎn)生新的app,如果沒有卸載重裝,每次請求獲得的device token是不變的。
另外官網(wǎng)也對device token的變化進行了說明:

To protect user privacy, do not use device tokens to identify user devices. Device tokens change when the user updates the operating system and when a device’s data and settings are erased. As a result, apps should always request the current device token at launch time.

// ios 10 support 處于前臺時接收到通知

// ios 10 support 處于前臺時接收到通知
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler
{
    NSDictionary * userInfo = notification.request.content.userInfo;
    if ([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
// 添加各種需求。。。。。
    }
    completionHandler(UNNotificationPresentationOptionAlert); 
// 處于前臺時,添加需求,一般是彈出alert跟用戶進行交互,這時候completionHandler(UNNotificationPresentationOptionAlert)這句話就可以注釋掉了,這句話是系統(tǒng)的alert,顯示在app的頂部,
}
    */ 如果處于前臺時需要自定義彈框或者彈出alert,可以看一下http://www.itdecent.cn/p/d2a42072fad9 這篇文章

// iOS 10 Support 點擊處理事件

// iOS 10 Support  點擊處理事件
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    // Required
    
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
        //推送打開
        if (userInfo)
        {
            // 取得 APNs 標準信息內(nèi)容
//            NSDictionary *aps = [userInfo valueForKey:@"aps"];
//            NSString *content = [aps valueForKey:@"alert"]; //推送顯示的內(nèi)容
//            NSInteger badge = [[aps valueForKey:@"badge"] integerValue]; //badge數(shù)量
//            NSString *sound = [aps valueForKey:@"sound"]; //播放的聲音
            
           // 添加各種需求。。。。。
        
        [JPUSHService handleRemoteNotification:userInfo];
        completionHandler(UIBackgroundFetchResultNewData);
    }
    completionHandler();  // 系統(tǒng)要求執(zhí)行這個方法
}

// iOS7 及以上接收到通知

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    // Required, iOS 7 Support
    [JPUSHService handleRemoteNotification:userInfo];
    completionHandler(UIBackgroundFetchResultNewData);
}

這里在iOS7及以上系統(tǒng)的方法中,如果需要在前臺和后臺做不同的處理的時候,需要判斷一下app 的狀態(tài),判斷方式如下

 if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
        
        // 處于前臺時 ,添加各種需求代碼。。。。

    }else if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
    {
        // app 處于后臺 ,添加各種需求
    }

那么問題來了,前臺后臺收到推送的方法都有了,還有一種情況。。。。。程序完全退出的時候,這種情況下,點擊通知會走下面這個方法(即注冊通知時的方法,程序的入口)

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

在這個方法里,我們需要判斷一下程序是否處于完全退出狀態(tài),判斷方法如下

 NSDictionary *remoteNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
   
    if (remoteNotification)
    {

   // 程序完全退出時,點擊通知,添加需求。。。

  }
# 需要注意的地方:
有可能有些小伙伴在集成過程中用ios10的手機測試的時候,
在推送通知的時候ios10和ios7的兩個代理方法都走了,具體原因具體對待,如果實在找
不到問題所在,這里提供兩個方法,one:在ios10的兩個代理方法的首尾加入以下語句
#ifdef NSFoundationVersionNumber_iOS_9_x_Max 
#endif      // ios10中加入這兩句話
在ios7的代理方法首尾加入以下語句
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1  
#endif   // ios7中加入這兩句話
第二種方法是直接在ios7的代理方法中加入判斷:
if ([[UIDevice currentDevice].systemVersion floatValue] < 10.0)

// 基于iOS 6 及以下的系統(tǒng)版本 接收到通知

// 基于iOS 6 及以下的系統(tǒng)版本,如果 App狀態(tài)為正在前臺或者點擊通知欄的通知消息,那么此函數(shù)將被調(diào)用,并且可通過AppDelegate的applicationState是否為UIApplicationStateActive判斷程序是否在前臺運行。此種情況在此函數(shù)中處理:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    // Required,For systems with less than or equal to iOS6
    
    // iOS 10 以下 Required
     [JPUSHService handleRemoteNotification:userInfo];
}

//最后清除角標

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [[UIApplication alloc] setApplicationIconBadgeNumber:0];
}

// 點擊之后badge清零
- (void)applicationWillEnterForeground:(UIApplication *)application {
    
    [application setApplicationIconBadgeNumber:0];
    [[UNUserNotificationCenter alloc] removeAllPendingNotificationRequests];
}

其他功能:

1 . 后臺傳入不同的值,點擊通知進入不同的界面,可以在極光的官網(wǎng)發(fā)送通知界面,展開可選設(shè)置,使用附加字段,這里我加了一個鍵值對key和值可以自行設(shè)置,然后在工程中需要進行判斷,

設(shè)置附加字段

代碼如下:大家可以在點擊通知會走的方法中調(diào)用此方法

// 傳入字段,根據(jù)字段改變需求
- (void)ExtrasOfNotificationWithUserInfo:(NSDictionary *)userInfo
{
    if (userInfo)
    {
        // 取得 APNs 標準信息內(nèi)容
//        NSDictionary *aps = [userInfo valueForKey:@"aps"];
//        NSString *content = [aps valueForKey:@"alert"]; //推送顯示的內(nèi)容
//        NSInteger badge = [[aps valueForKey:@"badge"] integerValue]; //badge數(shù)量
//        NSString *sound = [aps valueForKey:@"sound"]; //播放的聲音
        // 取得Extras字段內(nèi)容
        NSString *customizeField1 = [userInfo valueForKey:@"key"]; //服務(wù)端中Extras字段,key是自己定義的,需要與極光的附加字段一致
        // 若傳入字段的值為1,進入相應(yīng)的頁面
        if ([customizeField1 integerValue] == 1){
            //是推送打開
            UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
            MainTabbarVC *rootTabBarC = [sb instantiateViewControllerWithIdentifier:@"MainTabbarVC"];
            [UIApplication sharedApplication].delegate.window.rootViewController = rootTabBarC;
// 下面的方法是自己封裝的
            [rootTabBarC enterToElectronicInvoice];
        }
    }
    
}
 注意:這里的跳轉(zhuǎn)方法可能不適用所有項目,大家可以看一下下面的鏈接,或許能夠找到適合你工程的跳轉(zhuǎn)方法

1.2 極光的點擊通知的方法- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler 是對系統(tǒng)方法的封裝,他的userInfo中含有自定義添加的key,但是其他三方庫例如AWS的推送機制中就不包含自定義添加的key,這時候只能通過aps中的默認userInfo傳遞特定的值,aps的結(jié)構(gòu)如下

iOS 10 之前
{  
   "aps":{  
      "alert":"內(nèi)容",
      "badge":1,
      "sound":"default",
      "userinfo":{"username":"tom"}
   }
}


iOS 10及之后(iOS7、iOS8、iOS9可通用此模板)
{  
   "aps":{  
      "alert":{  
         "title":"標題", // 
         "subtitle":"子標題", // 一般使用title就能滿足需求
         "body":"內(nèi)容"
      },
      "badge":1, //角標數(shù)
      "sound":"default", //聲音
      "userinfo":{ //通知內(nèi)容信息
           "playid":"123",
           "username":"tom",
           "sex":1
      }
   }
}

如果只傳遞一串字符串或者不是按照上述格式發(fā)送通知消息,那么會默認把你傳遞的字符串全部轉(zhuǎn)化成alert的內(nèi)容,全部彈出來,所以在aws中我們可以這樣定義

APNS_SANDBOX : "{"aps":{"alert":" title message", "userInfo":"username"}}"

這樣在app中收到的彈出消息僅僅為title message ,而userInfo可以用來做其他的用處

2 . 指定用戶發(fā)送遠程通知,這里指定用戶不能只根據(jù)DeviceToken來進行發(fā)送,在極光的官網(wǎng)也沒有可以使用DeviceToken發(fā)送的選項,如下圖

極光發(fā)送消息針對的人群

這里的Registration ID 并不是DeviceToken,話不多說,下面我們介紹一種使用別名Alias的方法,我們知道指定用戶發(fā)送,無非是已經(jīng)注冊了本公司賬號的人群,你想給不同的人推不同的消息,那么我們指定用戶的時候,實際上是根據(jù)用戶在我們公司注冊的賬號進行發(fā)送特定消息,例如用戶的賬單狀態(tài)等等,所以我們可以在用戶登陸賬號之后,給用戶分配一個id用做唯一標示,綁定極光的別名或者tag,當然這里綁定別名還是tag可以和后臺商量一下,用什么其實都是可以的,代碼如下

[JPUSHService setTags:nil alias:USER_INFO.userID fetchCompletionHandle:^(int iResCode, NSSet *iTags, NSString *iAlias) {
                NSLog(@"設(shè)置結(jié)果:%i 用戶別名:%@",iResCode,USER_INFO.userID);
            }];
// 這是極光提供的方法,USER_INFO.userID是用戶的id,你可以根據(jù)賬號或者其他來設(shè)置,只要保證唯一便可


// 不要忘了在登出之后將別名置空
[JPUSHService setTags:nil alias:@"" fetchCompletionHandle:^(int iResCode, NSSet *iTags, NSString *iAlias) {
        NSLog(@"設(shè)置結(jié)果:%i 用戶別名:%@",iResCode,USER_INFO.userID);
    }];

綁定完別名之后,指定用戶發(fā)送消息的任務(wù)就可以交給后臺了。如果你想自己測試一下,那就打印一下USER_INFO.userID ,然后自己用極光給自己推送,如圖

根據(jù)自己的Alias給自己推送消息

有些朋友問我為啥收到通知有些方法就是不調(diào)用,這里要細心一點,有些方法是需要點擊alert才會走,如果發(fā)送通知沒有走進你想調(diào)試的方法里注意一下,是不是需要點擊一下alert

至此,ios極光推送的集成就簡單說到這里,未完。。。待續(xù)。。。覺得好的,就點個贊,有問題的可以私信我,或者加我qq:1162719523,同不同意那就不知道了

ios 收到遠程通知,彈出提示框,點擊確定跳轉(zhuǎn)到消息界面:http://www.itdecent.cn/p/d2a42072fad9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容