App開發中經常會使用到推送,蘋果和安卓差別是蘋果用自己的APNS推送伺服器,不論我們是內建第三方推送
還是用蘋果系統的推送都要經過APNS推送伺服器。
目前市場上比較流行的幾個第三方推送:
1.極光推送 (使用較多,但是偶爾會出現crash,crash定位在jPush SDK沒法解決,會出現推送延遲的情況)
2.阿裡雲推送(推出時間較短,目前可能會出現一些問題,支援全量推送、裝置号推送、賬号推送,注意阿裡雲推送推送消息和推送通知走的是兩個不同的接口,
同時支援通知和應用内消息推送,api多語言,接口靈活)
3.騰訊推送(性能上還是可以的,因為項目是選擇用的極光,騰訊推送沒有經過實際大批量的驗證,以後用到了會進行補充)
4.百度雲推送(免費、不穩定,裝置綁定時常失效,背景界面不易調用)
5.個推(10000台線上連接配接數(約為DAV的70%)以上收費、偶爾會不穩定)
6.友盟推送(免費、相對穩定的到達率,背景界面醫用,可統計打開率(部分功能待優化)、可設定發送速度)
以上的廠商提供的推送服務,如果是中小型的項目免費的就可以,但是如果使用者量比較大,還是建議使用
收費的推送,相對來說收費開通的通道和資源比較多,減少了很多不必要的問題
推送和通知NSNotification 的差別
1.NSNotification是系統内部發出的通知,一般用于内部事件的監聽,或者狀态的改變等、是不可見的(建議不要濫用NSNotification,因為是在主線程中執行,使用不當會發生線程阻塞)
2.本地通知與遠端通知是可見的,主要使用者告知使用者或者發送一些App的内容更新,推送一些消息,讓App知道App内部發生了什麼事情。
iOS 常用的通知
1.本地推送通知:(Local Notification)
2.遠端推送通知:(Remote Notification)
iOS中通知顯示的效果
1.設定音效
2.設定橫幅
3.設定彈窗
4.鎖屏下也可以呈現
5.App圖示的數字 (注意:顯示彈窗或者橫幅效果是取決于使用者設定:通知中心-選擇應用-選擇下載下傳的通知模式)
通知的注意點:
1.App在前台運作的時候,通知不會展示出來
2.點選通知,預設會自動打開推送通知的App
3.不管App是否打開,通知都可以如期發出
1、本地推送通知:
一.關于通知注冊:
ios8之前:registerForRemoteNotificationTypes:
ios8之後:registerUserNotificationSettings
二.關于提醒角标
1.本地推送UILocalNotification的applicationIconBadgeNumber屬性隻會影響角标的顯示,不會影響通知欄的通知處理。
1)當applicationIconBadgeNumber>0時,角标會随applicationIconBadgeNumber而變化。
2)當applicationIconBadgeNumber=0時,角标維持推送前狀态不變。
3)當applicationIconBadgeNumber<0時,角标置0不顯示。
2.遠端推送的badge字段,隻會影響角标的顯示,不會影響通知欄的通知處理。
1)當badge>0時,角标會随badge而變化。
2)當badge=0時,角标維持不變。
3)當badge<0時,角标維持不變。
3.UIApplication的applicationIconBadgeNumber屬性既會影響角标的顯示,又會影響通知欄通知的處理。
1)當applicationIconBadgeNumber>0時,角标會随之變化,通知欄通知不變。
2)當applicationIconBadgeNumber=0時,角标變為0不顯示,通知欄通知清空。
3)當applicationIconBadgeNumber<0時,角标變為0不顯示,通知欄通知清空。
三.關于重複:
1. UILocalNotification.repeatInterval:repeatInterval的下限應該是NSCalendarUnitMinute,即每分鐘重複發送一次通知。如果設定為NSCalendarUnitSecond,那麼消息不會重複,每秒發送一次通知,iOS系統當然不會容許這樣的存在了。這裡比較不好的一點是NSCalendarUnit是個枚舉類型,該值不能自定義,例如你不能塞個10.0給它進而希望它每十秒重複一次。是以如果你想每20分鐘發送一次通知,一小時内發送3次,那麼隻能同時設定三個通知了。
2.若想設定複雜的重複通知,比如隻在每周的周一、周三重複,則隻能設定兩個通知,分别進行周重複提醒。
四.關于userInfo:userInfo可以攜帶使用者自定義的關于通知的資訊,通常可以用來作為不同通知的區分标志
五.關于接收通知:
1. 如果此時應用程式還在運作(無論是在前台還是在背景)則會調用-(void)application:(UIApplication *)applicationdidReceiveLocalNotification:(UILocalNotification *)notification(如果是遠端通知則通過application:(UIApplication *)applicationdidReceiveLocalNotification:(UILocalNotification *)notification)方法接收消息參數。參數中可以拿到notification對象,隻要讀取userInfo屬性區分不同的通知即可。
2. 如果應用程式已經完全退出此時會調用- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法:
1)通過點選通知欄通知進入:此時可以通路launchOptions中鍵為UIApplicationLaunchOptionsLocalNotificationKey的對象,這個對象就是發送的通知,由此對象再去通路userInfo。
2)通過點選圖示進入:可以通過[[UIApplication sharedApplication] scheduledLocalNotifications]擷取全部的排程通知,并通過userinfo進行區分
六:關于覆寫安裝:
如果我們的應用程式給系統發送的本地通知是周期性的,那麼即使把程式删了重裝,之前的本地通知在重裝時依然存在,沒有從系統中移除
通知的一些屬性:
// 枚舉值-發出通知的時間(有局限性)
@property(nonatomic) NSCalendarUnit repeatInterval;
// 自定義-發出通知的時間(可以自由設定時間)
@property(nonatomic,copy) NSCalendar *repeatCalendar;
// 區域-建立隻需要建立一個中心點與半徑就可以了
@property(nonatomic,copy) CLRegion *region
// 進入區域發出一個通知,設定yes,隻會發出一個通知,設定NO就會每次進入這個區域都發送
@property(nonatomic,assign) BOOL regionTriggersOnce NO
// 設定通知的内容
@property(nonatomic,copy) NSString *alertBody;
// 決定alertAction是否生效
@property(nonatomic) BOOL hasAction;
// 設定滑塊的文字
@property(nonatomic,copy) NSString *alertAction;
// 設定點選通知的啟動圖檔(一般設定App啟動圖檔後,這裡可以随便寫)
@property(nonatomic,copy) NSString *alertLaunchImage;
// 設定alertTitle,就是通知内容上面的文字
@property(nonatomic,copy) NSString *alertTitle
// 設定彈出的聲音
@property(nonatomic,copy) NSString *soundName;
// 設定App的消息條數
@property(nonatomic) NSInteger applicationIconBadgeNumber;
// 設定通知一些額外資料
@property(nonatomic,copy) NSDictionary *userInfo;
如何發出本地通知:
// 1.建立本地通知
UILocalNotification *localNote = [[UILocalNotification alloc] init];
// 2.設定本地通知的内容
// 2.1.設定通知發出的時間
localNote.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0];
// 2.2.設定通知的内容
localNote.alertBody = @"Good Morning?";
// 2.3.設定滑塊的文字(鎖屏狀态下:滑動來“解鎖”)
localNote.alertAction = @"解鎖";
// 2.4.決定alertAction是否生效
localNote.hasAction = NO;
// 2.5.設定點選通知的啟動圖檔
localNote.alertLaunchImage = @"$$$$";
// 2.6.設定alertTitle
localNote.alertTitle = @"您有一條新通知";
// 2.7.設定有通知時的音效
localNote.soundName = @"buyao.wav";
// 2.8.設定應用程式圖示右上角的數字
localNote.applicationIconBadgeNumber = 99;
// 2.9.設定額外資訊
localNote.userInfo = @{@"type" : @1};
// 3.調用通知
[[UIApplication sharedApplication] scheduleLocalNotification:localNote];
}
使用注意:
iOS7,不需要使用者授權就可發出通知,而iOS8以後,必須使用者授權才可以發出通知
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 設定應用程式的圖示右上角的數字
[application setApplicationIconBadgeNumber:0];
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
}
// 界面的跳轉(針對應用程式被殺死的狀态下的跳轉)
// 殺死狀态下的,界面跳轉并不會執行下面的方法- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification,
// 是以我們在寫本地通知的時候,要在這個與下面方法中寫,但要判斷,是通過哪種類型通知來打開的
if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) {
// 跳轉代碼
UILabel *redView = [[UILabel alloc] init];
redView.frame = CGRectMake(0, 0, 200, 300);
redView.numberOfLines = 0;
redView.font = [UIFont systemFontOfSize:12.0];
redView.backgroundColor = [UIColor redColor];
redView.text = [NSString stringWithFormat:@"%@", launchOptions];
[self.window.rootViewController.view addSubview:redView];
}
return YES;
}
監聽通知,如果使用者打開通知,可以讓使用者進入一些特定的界面
/*
應用程式在進入前台,或者在前台的時候都會執行該方法
*/
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// 必須要監聽--應用程式在背景的時候進行的跳轉
if (application.applicationState == UIApplicationStateInactive) {
NSLog(@"進行界面的跳轉");
// 如果在上面的通知方法中設定了一些,可以在這裡列印額外資訊的内容,就做到監聽,也就可以根據額外資訊,做出相應的判斷
NSLog(@"%@", notification.userInfo);
//
UIView *redView = [[UIView alloc] init];
redView.frame = CGRectMake(0, 0, 100, 100);
redView.backgroundColor = [UIColor redColor];
[self.window.rootViewController.view addSubview:redView];
}
}
2、遠端推送通知:
遠端推送服務APNS(Apple Push Notification Servers) 所有蘋果裝置在聯網的情況下都會與蘋果建立長連接配接 長連接配接: 1.隻要聯網就一直建立連接配接 2.長連接配接作用:1.時間校準2.系統更新3.查找我的iPhone等 長連接配接的好處 1.資料傳輸速度快 2.資料保持最新狀态 遠端推送的基本過程 1.用戶端app需要将使用者的UUID和app的bundleID發送給apps伺服器,進行注冊,apps伺服器将加密後的Device Token傳回給app 2.app獲得Device Token後,上傳到公司的伺服器 3.當需要推送通知時,公司的伺服器會将推送内容和Device Token一起發給apns伺服器 4.apns 再将推送的内容推送給用戶端
用戶端要做的事情
1.注冊蘋果獲得Device Token 2.得到蘋果傳回的Device Token 3.發送Device Token給公司伺服器 4.監聽使用者通知的點選 調試遠端推送功能時,需要真機調試,模拟器接受不到遠端通知 真機測試相關内容 1.建立apeid(不帶*) 2.建立appid ssl 證書(獲得一個調試證書,一個釋出證書) 3.生成相應的描述檔案 4.安裝相關證書
為什麼使用遠端推送? 解決傳統擷取資料的局限性,讓資料實時更新 使用場景 聊天功能(非及時聊天)、推送版本下載下傳、app活動、app内部新功能等

如何推送
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { //iOS8
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
} else { // iOS7
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNewsstandContentAvailability | UIRemoteNotificationTypeSound |UIRemoteNotificationTypeAlert];
}
// 根據遠端通知通過UIApplicationLaunchOptionsRemoteNotificationKey打開的情況來進行
if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {
// 跳轉
// 添加一個紅色的View
}
return YES;
}
// 擷取DeviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 将DeviceToken傳給伺服器
NSLog(@"%@", deviceToken.description);
}
// 正常接到遠端通知的時候會調用這個方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"%@", userInfo);
// 正常打開推送後,
}
// 背景操作(根據收到推送,讓程式自己執行一些操作,不管使用者是否點選推送)
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
NSLog(@"---------");
UIView *redV = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.frame = CGRectMake(100, 100, 100, 100);
[self.window.rootViewController.view addSubview:redV];
// 1.打開背景模式 2.告訴系統是否有新内容的更新 3.發送的通知有固定的格式("content-available":"1")
// 2.告訴系統有新内容
completionHandler(UIBackgroundFetchResultNewData);
}
1、打開背景模式 在Capabilities中找到Background Modes 設定YES
2、告訴系統有新内容
completionHandler(UIBackgroundFetchResultNewData);
3、發送通知有固定格式
("content-available":"1")