參考文章:
本地推送:一、iOS推送之本地推送(iOS Notification Of Local Notification)
二、iOS中使用本地通知為你的APP添加提示用戶功能
遠(yuǎn)程推送:一、iOS推送之遠(yuǎn)程推送(iOS Notification Of Remote Notification)
二、iOS本地推送與遠(yuǎn)程推送詳解
注:此文現(xiàn)在已經(jīng)不能適配iOS10了,iOS10的推送采用了新的方法,做iOS9及以下的系統(tǒng)可讀此篇文章。
iOS10的推送方法可以查看:iOS10-推送(本地和遠(yuǎn)程)的簡(jiǎn)單使用
tips:1.如果想要將通知欄上方的通知清除,只要將APP的角標(biāo)置為0就可以了。
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
IOS中消息的推送有兩種方式,分別是本地推送和遠(yuǎn)程推送(APNS)。
一、本地推送
本地推送介紹
本地推送和遠(yuǎn)程推送的功能是一樣的,都是要提醒用戶去做某些事情。但是和遠(yuǎn)程推送不同的就是本地推送是不需要設(shè)備聯(lián)網(wǎng)的,而遠(yuǎn)程推送是必需要設(shè)備聯(lián)網(wǎng)的,因?yàn)橹挥新?lián)網(wǎng)狀態(tài)下,才能和蘋果的APNs服務(wù)器建立長(zhǎng)連接,從而推送消息。本地推送是由App自己設(shè)定的,并且發(fā)送給安裝此App的這臺(tái)設(shè)備,屬于一對(duì)一的對(duì)應(yīng)關(guān)系。
首先,我們先要明白一個(gè)概念,這里的本地推送是UILocalNotification類,和系統(tǒng)的NSNotificationCenter通知中心是完全不同的概念。
本地推送,實(shí)際上是由IOS系統(tǒng)管理的一個(gè)功能,比如某些后臺(tái)應(yīng)用做了某項(xiàng)活動(dòng)需要我們處理、已經(jīng)退出的應(yīng)用在某個(gè)時(shí)間提醒我們喚起等等,如果注冊(cè)了通知,系統(tǒng)都會(huì)在通知觸發(fā)時(shí)給我們發(fā)送消息。由此,我們可以通過系統(tǒng)給我們的APP添加通知用戶的功能,并且應(yīng)用非常廣泛。例如,鬧種類應(yīng)用,有按時(shí)簽到相似功能的應(yīng)用。
注意:一個(gè)App最多只能設(shè)置64個(gè)本地推送,當(dāng)超過此限制的時(shí)候,系統(tǒng)會(huì)自動(dòng)忽略多余的本地推送,而保留能最快觸發(fā)的64個(gè)。循環(huán)的本地推送會(huì)被系統(tǒng)認(rèn)為是同一個(gè)本地推送。
創(chuàng)建本地推送,需要用到UILocalNotification類
先來(lái)看它的幾個(gè)屬性:
@property(nonatomic,copy) NSDate *fireDate; 設(shè)置系統(tǒng)發(fā)送通知的時(shí)間(如果是過去的時(shí)間或者0,則會(huì)立刻發(fā)起通知)
@property(nonatomic,copy) NSTimeZone *timeZone;// 設(shè)置時(shí)間的時(shí)區(qū)
@property(nonatomic) NSCalendarUnit repeatInterval;// 設(shè)置周期性通知
NSCalendarUnit對(duì)象是枚舉,設(shè)定通知的周期
typedef NS_OPTIONS(NSUInteger, NSCalendarUnit) {
NSCalendarUnitEra = kCFCalendarUnitEra,
NSCalendarUnitYear = kCFCalendarUnitYear,
NSCalendarUnitMonth = kCFCalendarUnitMonth,
NSCalendarUnitDay = kCFCalendarUnitDay,
NSCalendarUnitHour = kCFCalendarUnitHour,
NSCalendarUnitMinute = kCFCalendarUnitMinute,
NSCalendarUnitSecond = kCFCalendarUnitSecond,
NSCalendarUnitWeekday = kCFCalendarUnitWeekday,
NSCalendarUnitWeekdayOrdinal = kCFCalendarUnitWeekdayOrdinal,
}
@property(nonatomic,copy) NSCalendar *repeatCalendar;// 設(shè)置周期性通知參照的日歷表,NSCalendar的使用方法請(qǐng)自行查找
@property(nonatomic,copy) CLRegion *region;// 在用戶進(jìn)去或者離開某一區(qū)域時(shí)發(fā)送通知
@property(nonatomic,assign) BOOL regionTriggersOnce; 設(shè)置區(qū)域檢測(cè)通知是否重復(fù)(如果為YES,則沒次進(jìn)入該區(qū)域都會(huì)發(fā)送,否則只發(fā)送一次)
@property(nonatomic,copy) NSString *alertBody; // 設(shè)置通知的主體內(nèi)容
@property(nonatomic) BOOL hasAction; //是否隱藏滑動(dòng)啟動(dòng)按鈕
@property(nonatomic,copy) NSString *alertAction;// 設(shè)置滑動(dòng)打開的提示文字
@property(nonatomic,copy) NSString *alertLaunchImage; // 設(shè)置點(diǎn)擊通知后啟動(dòng)的啟動(dòng)圖片
@property(nonatomic,copy) NSString *alertTitle;//通知的短標(biāo)題
@property(nonatomic,copy) NSString *soundName; // 收到通知時(shí),播放的系統(tǒng)音
@property(nonatomic) NSInteger applicationIconBadgeNumber; //設(shè)置應(yīng)用程序Icon頭標(biāo)數(shù)字
@property(nonatomic,copy) NSDictionary *userInfo; // 用戶字典,可用于傳遞通知消息參數(shù)
NSString *const UILocalNotificationDefaultSoundName; // 推送提示音,注意:這個(gè)字符串是系統(tǒng)默認(rèn)的提示音
創(chuàng)建一個(gè)本地推送通知
// 在需要添加本地通知的地方進(jìn)行添加處理
// 1.創(chuàng)建一個(gè)本地通知
UILocalNotification *localNote = [[UILocalNotification alloc] init];
// 1.1.設(shè)置通知發(fā)出的時(shí)間
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:100];
//設(shè)置重復(fù)間隔
localNote.repeatInterval = NSCalendarUnitMinute;
// 1.2.設(shè)置通知內(nèi)容
localNote.alertBody = @"這是一個(gè)推送這是一個(gè)推送";
// 1.3.設(shè)置鎖屏?xí)r,字體下方顯示的一個(gè)文字
// localNote.alertAction = @"趕緊!!!!!";
// 1.4.設(shè)置啟動(dòng)圖片(通過通知打開的)
localNote.alertLaunchImage = @"144";
// 1.5.設(shè)置通過到來(lái)的聲音
localNote.soundName = UILocalNotificationDefaultSoundName;
// 1.6.設(shè)置應(yīng)用圖標(biāo)左上角顯示的數(shù)字
localNote.applicationIconBadgeNumber = 999;
// 1.7.設(shè)置一些額外的信息
localNote.userInfo = @{@"qq" : @"1234567", @"msg" : @"success"};
// 2 設(shè)置好本地推送后必須調(diào)用此方法啟動(dòng)此推送
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
現(xiàn)在,一個(gè)簡(jiǎn)單的本地推送已經(jīng)創(chuàng)建好了,如果需要在推送執(zhí)行完畢后,取消推送,可以使用下面的方法
// 1、取消某一個(gè)通知
NSArray *notificaitons = [[UIApplication sharedApplication] scheduledLocalNotifications];
//獲取當(dāng)前所有的本地通知
if (!notificaitons || notificaitons.count <= 0) {
return;
}
for (UILocalNotification *notify in notificaitons) {
if ([[notify.userInfo objectForKey:@"id"] isEqualToString:@"想要取消的推送的標(biāo)識(shí)符"]) {
//取消一個(gè)特定的通知
[[UIApplication sharedApplication] cancelLocalNotification:notify];
break;
}
}
// 2、取消所有的本地通知
[[UIApplication sharedApplication] cancelAllLocalNotifications];
本地推送的注冊(cè)與處理
分為本地推送和遠(yuǎn)程推送2種??梢栽趹?yīng)用沒有打開甚至手機(jī)鎖屏情況下給用戶以提示。它們都需要注冊(cè),注冊(cè)后系統(tǒng)會(huì)彈出提示框(如下圖)提示用戶是否同意,如果同意則正常使用;如果用戶不同意則下次打開程序也不會(huì)彈出該提示框,需要用戶到設(shè)置里面設(shè)置。一共有三種提示類型:
UIUserNotificationTypeBadge:應(yīng)用圖標(biāo)右上角的信息提示
UIUserNotificationTypeSound:播放提示音
UIUserNotificationTypeAlert:提示框
APP安裝后,第一次打開時(shí),會(huì)彈出提示框詢問用戶是否允許推送,用戶選擇之后,以后都不會(huì)再進(jìn)行提示,除非用戶卸載重裝:

想要正常進(jìn)行推送,就必須要進(jìn)行注冊(cè):
/// 一般在程序啟動(dòng)時(shí)注冊(cè)通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (10.0>[[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { // iOS8
// categories 可以設(shè)置不同類別的推送,在收到推送的代理方法中根據(jù)categories的identifier進(jìn)行不同的推送處理
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:setting];
}
// 如果用戶對(duì)程序進(jìn)行滑飛操作,程序進(jìn)程被殺死后,重新啟動(dòng)APP,推送的代理方法是不走的,這個(gè)時(shí)候就可以添加下面的代碼,獲取到推送,進(jìn)行對(duì)應(yīng)的操作。
NSDictionary *userInfoLocal = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (userInfoLocal) {
// 這里添加處理代碼
NSLog(@"=== Local:%@", userInfoLocal);
}
return YES;
}
接下來(lái)就需要對(duì)收到的推送信息進(jìn)行處理了
/** 獲取用戶對(duì)通知的設(shè)置信息 */ //NS_AVAILABLE_IOS(8_0);
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
}
// 程序處于前臺(tái)(或者程序處于后臺(tái),但是用戶點(diǎn)擊了收到的通知信息),就會(huì)運(yùn)行該方法 //NS_AVAILABLE_IOS(4_0, 10_0);
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
/* notification === <UIConcreteLocalNotification: 0x127579610>{fire date = 2016年12月19日 星期一 中國(guó)標(biāo)準(zhǔn)時(shí)間 上午11:31:27, time zone = (null), repeat interval = NSCalendarUnitMinute, repeat count = UILocalNotificationInfiniteRepeatCount, next fire date = 2016年12月19日 星期一 中國(guó)標(biāo)準(zhǔn)時(shí)間 上午11:32:27, user info = {
msg = success;
qq = 1234567;
}}*/
// 這里添加處理代碼
}
如果在上面注冊(cè)通知的時(shí)候,攜帶了 categories 參數(shù),則會(huì)調(diào)用下面的方法。
//NS_AVAILABLE_IOS(8_0, 10_0);
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void(^)())completionHandler {
// identifier是識(shí)別符,
//處理完消息,最后一定要調(diào)用這個(gè)代碼塊
completionHandler();
}
// 下面這個(gè)方法是 9.0新加的,如果要是適配8.0,只需要用上面的方法就可以了,參數(shù) responseInfo 可以通過 notification.userInfo 取到。
//NS_AVAILABLE_IOS(9_0, 10_0);
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler {
}
以上就是關(guān)于 iOS8.0-10.0 的本地推送的使用了。
注:上面提到的有關(guān) categories 參數(shù)的使用,我沒有進(jìn)行測(cè)試,如果使用時(shí)有問題,歡迎給我留言。
二、遠(yuǎn)程推送
想要使用遠(yuǎn)程推送,需要先在開發(fā)者網(wǎng)站申請(qǐng)推送證書
遠(yuǎn)程推送原理
注:(從作者TIME_for的文章復(fù)制過來(lái)的)
學(xué)習(xí)一些東西前我認(rèn)為最好能了解它的原理,這樣以后我們遇到問題的時(shí)候,就可以很快速的找到錯(cuò)誤之所在,如果對(duì)原理不感興趣的同學(xué)可直接下翻到應(yīng)用部分。
iOS app大多數(shù)都是基于client/server模式開發(fā)的,client就是安裝在我們?cè)O(shè)備上的app,server就是遠(yuǎn)程服務(wù)器,主要給我們的app提供數(shù)據(jù),因?yàn)橐脖环Q為Provider。那么問題來(lái)了,當(dāng)App處于Terminate狀態(tài)的時(shí)候,當(dāng)client與server斷開的時(shí)候,client如何與server進(jìn)行通信呢?是的,這時(shí)候Remote Notifications很好的解決了這個(gè)困境。蘋果所提供的一套服務(wù)稱之為Apple Push Notification service,就是我們所謂的APNs。
推送消息傳輸路徑: Provider-APNs-Client App
我們的設(shè)備聯(lián)網(wǎng)時(shí)(無(wú)論是蜂窩聯(lián)網(wǎng)還是Wi-Fi聯(lián)網(wǎng))都會(huì)與蘋果的APNs服務(wù)器建立一個(gè)長(zhǎng)連接(persistent IP connection),當(dāng)Provider推送一條通知的時(shí)候,這條通知并不是直接推送給了我們的設(shè)備,而是先推送到蘋果的APNs服務(wù)器上面,而蘋果的APNs服務(wù)器再通過與設(shè)備建立的長(zhǎng)連接進(jìn)而把通知推送到我們的設(shè)備上(參考圖1-1,圖1-2)。而當(dāng)設(shè)備處于非聯(lián)網(wǎng)狀態(tài)的時(shí)候,APNs服務(wù)器會(huì)保留Provider所推送的最后一條通知,當(dāng)設(shè)備轉(zhuǎn)換為連網(wǎng)狀態(tài)時(shí),APNs則把其保留的最后一條通知推送給我們的設(shè)備;如果設(shè)備長(zhǎng)時(shí)間處于非聯(lián)網(wǎng)狀態(tài)下,那么APNs服務(wù)器為其保存的最后一條通知也會(huì)丟失。Remote Notification必須要求設(shè)備連網(wǎng)狀態(tài)下才能收到,并且太頻繁的接收遠(yuǎn)程推送通知對(duì)設(shè)備的電池壽命是有一定的影響的。

deviceToken的生成
當(dāng)一個(gè)App注冊(cè)接收遠(yuǎn)程通知時(shí),系統(tǒng)會(huì)發(fā)送請(qǐng)求到APNs服務(wù)器,APNs服務(wù)器收到此請(qǐng)求會(huì)根據(jù)請(qǐng)求所帶的key值生成一個(gè)獨(dú)一無(wú)二的value值也就是所謂的deviceToken,而后APNs服務(wù)器會(huì)把此deviceToken包裝成一個(gè)NSData對(duì)象發(fā)送到對(duì)應(yīng)請(qǐng)求的App上。然后App把此deviceToken發(fā)送給我們自己的服務(wù)器,就是所謂的Provider。Provider收到deviceToken以后進(jìn)行儲(chǔ)存等相關(guān)處理,以后Provider給我們的設(shè)備推送通知的時(shí)候,必須包含此deviceToken。
這個(gè)時(shí)候你可能會(huì)問deviceToken到底是什么?有什么用?為什么是獨(dú)一無(wú)二的?
是什么:deviceToken其實(shí)就是根據(jù)注冊(cè)遠(yuǎn)程通知的時(shí)候向APNs服務(wù)器發(fā)送的Token key,Token key中包含了設(shè)備的UDID和App的Bundle Identifier,然后蘋果APNs服務(wù)器根據(jù)此Token key編碼生成一個(gè)deviceToken。deviceToken可以簡(jiǎn)單理解為就是包含了設(shè)備信息和應(yīng)用信息的一串編碼。
有什么用:上面提到Provider推送消息的時(shí)候必須帶有此deviceToken,然后此消息就根據(jù)deviceToken(UDID + App's Bundle Identifier)找到對(duì)應(yīng)的設(shè)備以及該設(shè)備上對(duì)應(yīng)的應(yīng)用,從而把此推送消息推送給此應(yīng)用。
唯一性:蘋果APNs的編碼技術(shù)和deviceToken的獨(dú)特作用保證了他的唯一性。每臺(tái)設(shè)備的 deviceToken都是不一樣的。
注:deviceToken也是會(huì)變的,將用戶將程序卸載重裝或者用戶升級(jí)系統(tǒng)的時(shí)候deviceToken是會(huì)變化的。 ”If the user restores backup data to a new device or computer, or reinstalls the operating system, the device token changes“,因此應(yīng)每次都發(fā)給服務(wù)器(provider)
遠(yuǎn)程推送的注冊(cè)與處理
遠(yuǎn)程推送的注冊(cè)
遠(yuǎn)程推送的注冊(cè)與本地推送相比,只需要加一行代碼就可以了。
/// 一般在程序啟動(dòng)時(shí)注冊(cè)通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (10.0>[[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { // iOS8
// categories 可以設(shè)置不同類別的推送,在收到推送的代理方法中根據(jù)categories的identifier進(jìn)行不同的推送處理
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:setting];
}
/**注冊(cè)遠(yuǎn)程通知要添加的代碼,該代碼可以寫在這里,也可以寫在獲取用戶設(shè)置推送信息的回調(diào)方法里,didRegisterUserNotificationSettings*/
[[UIApplication sharedApplication] registerForRemoteNotifications];
/*
// iOS7及其之后,無(wú)論是程序被殺死還是處于后臺(tái),只要用戶點(diǎn)擊了通知,都會(huì)調(diào)用“- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler ”方法,因此如果是iOS7及以上系統(tǒng),則不必在didFinishLaunchingWithOptions中做處理,只在該方法中做處理即可,此時(shí)應(yīng)避免在didFinishLaunchingWithOptions函數(shù)中也做重復(fù)處理。
NSDictionary *userInfoLocal = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (userInfoLocal) {
// 這里添加處理代碼
NSLog(@"=== Local:%@", userInfoLocal);
}
*/
return YES;
}
遠(yuǎn)程推送的代理方法
/** 獲取用戶對(duì)通知的設(shè)置信息 */ //NS_AVAILABLE_IOS(8_0);
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
}
/** 遠(yuǎn)程通知注冊(cè)成功委托 */ //NS_AVAILABLE_IOS(3_0);
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// 對(duì) deviceToken 進(jìn)行處理
NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
// 需要把 deviceToken 上傳給服務(wù)器
/**上傳deviceToken的代碼*/
}
/** 遠(yuǎn)程通知注冊(cè)失敗委托 */ //NS_AVAILABLE_IOS(3_0);
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"%@",error);
}
收到遠(yuǎn)程推送的回調(diào)方法
// 收到遠(yuǎn)程推送時(shí),程序在前臺(tái),或者程序在后臺(tái)但是點(diǎn)擊了收到的推送通知打開程序 //NS_AVAILABLE_IOS(7_0);
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
// 在此方法中一定要調(diào)用completionHandler這個(gè)回調(diào),告訴系統(tǒng)是否處理成功
// UIBackgroundFetchResultNewData, 成功接收到數(shù)據(jù)
// UIBackgroundFetchResultNoData, 沒有接收到數(shù)據(jù)
// UIBackgroundFetchResultFailed 接受失敗
if (userInfo) {
completionHandler(UIBackgroundFetchResultNewData);
} else {
completionHandler(UIBackgroundFetchResultNoData);
}
}
//NS_AVAILABLE_IOS(3_0, 10_0); // 如果是iOS8.0以上的系統(tǒng),不會(huì)運(yùn)行該方法,只會(huì)運(yùn)行上面的方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
}
如果在上面注冊(cè)通知的時(shí)候,攜帶了 categories 參數(shù),則會(huì)調(diào)用下面的方法。
//NS_AVAILABLE_IOS(8_0, 10_0);
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler {
//處理完消息,最后一定要調(diào)用這個(gè)代碼塊
completionHandler();
}
// 下面這個(gè)方法是 9.0新加的,如果要是適配8.0,只需要用上面的方法就可以了,參數(shù) responseInfo 可以通過 notification.userInfo 取到。
//NS_AVAILABLE_IOS(9_0, 10_0);
- (void)application:(UIApplication *)application handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void(^)())completionHandler {
}
設(shè)置程序后臺(tái)運(yùn)行
設(shè)置后臺(tái)運(yùn)行后,收到遠(yuǎn)程推送后會(huì)調(diào)用方法:
application: didReceiveRemoteNotification: fetchCompletionHandler:
iOS7之前蘋果是不支持多任務(wù)的,這也是iOS系統(tǒng)對(duì)硬件要求低,流暢性好的原因之一。iOS7之后,蘋果開始支持多任務(wù),即App可在后臺(tái)做一些更新UI、下載數(shù)據(jù)的操作等。若要接收到遠(yuǎn)程推送的時(shí)候要在后臺(tái)做一些事情則需要把后臺(tái)遠(yuǎn)程推送模式打開。不適配iOS7之前系統(tǒng)的項(xiàng)目建議使用此后臺(tái)模式,充分利用蘋果推出的多任務(wù)模式,不枉費(fèi)蘋果的一片苦心??!設(shè)置后臺(tái)模式方法項(xiàng)目對(duì)應(yīng)TARGETS-Capabilities-Background Modes-Remote Notifications具體設(shè)置方法如下圖。

遠(yuǎn)程推送負(fù)載
遠(yuǎn)程推送負(fù)載大小
遠(yuǎn)程通知負(fù)載的大小根據(jù)Provider使用的API不同而不同。當(dāng)使用HTTP/2 provider API時(shí),負(fù)載最大為4096bytes,即4kB;當(dāng)使用legacy binary interface時(shí),負(fù)載最大為2048bytes,即2kB。當(dāng)負(fù)載大小超過規(guī)定的負(fù)載大小時(shí),APNs會(huì)拒絕發(fā)送此消息。
遠(yuǎn)程推送負(fù)載內(nèi)容格式
一般公司服務(wù)端會(huì)要我們客戶端定義好格式給他們。
每一條通知的消息都會(huì)組成一個(gè)JSON字典對(duì)象,其格式如下所示,示例中的key值為蘋果官方所用key。自定義字段的時(shí)候要避開這些key值。
{ "aps" : {
"alert" : { // string or dictionary
"title" : "string"
"body" : "string",
"title-loc-key" : "string or null"
"title-loc-args" : "array of strings or null"
"action-loc-key" : "string or null"
"loc-key" : "string"
"loc-args" : "array of strings"
"launch-image" : "string"
},
"badge" : number,
"sound" : "string"
"content-available" : number;
"category" : "string"
},
}
aps:推送消息必須有的keyalert:推送消息包含此key值,系統(tǒng)就會(huì)根據(jù)用戶的設(shè)置展示標(biāo)準(zhǔn)的推送信息
badge:在app圖標(biāo)上顯示消息數(shù)量,缺少此key值,消息數(shù)量就不會(huì)改變,消除標(biāo)記時(shí)把此key對(duì)應(yīng)的value設(shè)置為0
sound:設(shè)置推送聲音的key值,系統(tǒng)默認(rèn)提示聲音對(duì)應(yīng)的value值為default
content-available:此key值設(shè)置為1,系統(tǒng)接收到推送消息時(shí)就會(huì)調(diào)用不同的回調(diào)方法,iOS7之后配置后臺(tái)模式
category:UIMutableUserNotificationCategory's identifier 可操作通知類型的key值
title:簡(jiǎn)短描述此調(diào)推送消息的目的,適用系統(tǒng)iOS8.2之后版本body:推送的內(nèi)容
title-loc-key:功能類似title,附加功能是國(guó)際化,適用系統(tǒng)iOS8.2之后版本
title-loc-args:配合title-loc-key字段使用,適用系統(tǒng)iOS8.2之后版本
action-loc-key:可操作通知類型key值,不詳細(xì)敘述
loc-key:參考title-loc-key
loc-args:參考title-loc-args
launch-image:點(diǎn)擊推送消息或者移動(dòng)事件滑塊時(shí),顯示的圖片。如果缺少此key值,會(huì)加載app默認(rèn)的啟動(dòng)圖片。
當(dāng)然以上key值并不是每條推送消息都必帶的key值,應(yīng)當(dāng)根據(jù)需求來(lái)選擇所需要的key值,除了以上系統(tǒng)所提供的key值外,你還可以自定義自己的key值,來(lái)作為消息推送的負(fù)載,自定義key值與aps此key值并列。如下格式:
{ "aps" : {
"alert" : "Provider push messag.",
"badge" : 9,
"sound" : "toAlice.aiff"
},
"Id" : 1314, // 自定義key值
"type" : "customType" // 自定義key值
}
推送函數(shù)的調(diào)用:
首次安裝后啟動(dòng):
didRegisterForRemoteNotificationsWithDeviceToken 被調(diào)用
系統(tǒng)詢問用戶是否同意接收 Notifications
不管用戶選擇同意或拒絕,didRegisterUserNotificationSettings 被調(diào)用
應(yīng)用非首次啟動(dòng)時(shí):
如果 notifications 處于拒絕狀態(tài):didRegisterUserNotificationSettings 被調(diào)用
如果 notifications 處于允許狀態(tài)
didRegisterForRemoteNotificationsWithDeviceToken 被調(diào)用
didRegisterUserNotificationSettings 被調(diào)用
應(yīng)用運(yùn)行過程中用戶修改 notifications 設(shè)置:
從拒絕變?yōu)樵试S:**didRegisterForRemoteNotificationsWithDeviceToken **被調(diào)用
從允許變?yōu)榫芙^:什么也不發(fā)生。
微信的推送簡(jiǎn)略圖
