本文講解iOS
的遠程通知的基本使用,主要包括遠程通知的類型,處理遠程通知的場景,以及遠程通知相關證書的配置等等。
一、APNs簡介
APNs
是蘋果公司提供的遠程通知的服務器,當App
處於後臺或者沒有運行時,如果後臺需要發送通知,那麼就需要藉助APNs
服務器。在App
接收通知的過程中,通知的發送路徑是:
Provider
-> APNs
服務器 -> iPhone
-> App
其中,Provider
和APNs
之間有一個TLS
連接,Provider
通過該連接將遠程通知發送到APNs
服務器;iPhone
與APNs
之間也有一個TLS
連接,APNs
將遠程通知通過該連接發送給iPhone
,進而通知用戶某App
有新通知。
iPhone
與APNs
連接圖如下:
注意:
- 此連接由系統建立並維持,無需開發人員管理;
- 上圖中的證書是蘋果設備本身的證書,與開發者賬號中申請的證書無關;
- 每個設備與
APNs
服務器只需維持一條連接。
Provider
與APNs
連接圖如下:
注意:
- 此連接由
App
的bundle ID
唯一確定 - 上圖中
Provider certificate
需要通過開發者賬號申請生成,其中包含App
的bundle ID
APNs
工作流程
注意:
- 首先客戶端需要向
APNs
服務器註冊當前App
,APNs
會返回一個Token
(注意這個過程要求App
有合法的證書,需要包含推送功能的證書);注意不同應用在同一設備上獲取的Token
不同,同一應用在不同設備上獲取的Token
也不同,所以Token
是跟設備與App
唯一綁定的 App
拿到Token
後需要將其發送給Provider
Provider
發送推送通知時,指定Token
和通知內容,併發送給APNs
服務器APNs
服務器會將通知發送給Token
對應的設備上- 設備收到通知後,根據
APNs
發過來的通知中帶有的bundle ID
信息區分是哪個App
的遠程通知(這裏應該是根據Token
來獲取bundle ID
)
APNs的Feedback 機制
Feedback
是 APNs
服務器提供的用於減少服務器壓力以及優化網絡的服務,工作流程圖如下:
注意:
Provider
發送一個遠程通知給APNs
服務器,APNs
服務器會檢測目的設備是否在線,如果不在線,那麼APNs
服務器會暫存該消息- 當目的設備上線後,
APNs
會發送暫存的消息給目的設備(按照蘋果官方說法暫存消息只會暫存最後一條消息,之前的消息會被丟棄); - 如果目的設備很久都沒有上線,那麼
APNs
消息會把該設備加入feedback
名單。Provider
可以定期去APNs
拉新feedback
名單; - 當
Provider
再次給之前的設備發送遠程通知時,需要檢查一下feedback
名單,如果設備在這個名單,則不再發送給APNs
了; - 當設備重新上線後,
Provider
可以再將此設備移除feedback
名單,當Provider
更新feedback list
後,就可以重新給該設備發送遠程通知了。當然,feedback list
的更新可能會有周期,如果需要及時有效的更新feedback list
,那麼需要App
打開後,及時通知Provider
; - 這種機制的好處就是防止發送多餘無用的遠程通知消息,一方面可以減緩
APNs
服務器的壓力,另一方面也可以減少網絡流量
二、證書配置
假定已經有開發證書的情況,下面只介紹配置推送證書的步驟
- 創建新的
App ID
- 創建推送證書和發佈證書
- 創建新的
Provisioning Profiles
三、通知類型
遠程通知具體可分爲普通遠程通知和靜默遠程通知
普通遠程通知
收到通知後,有文字和聲音,點擊通知會進入App
,然後執行如下方法
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
靜默遠程通知
收到通知後,沒有文字和聲音,不用點開通知,也不用打開App
,就能執行如下方法
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
靜默通知注意點:
aps
數據中一定要加"content-available" : 1
- 一定不能加
alert
,如果加入了alert
就不是靜默推送了 sound
和badge
也不能加
四、通知處理場景
1.申請通知權限
if (DEF_IOS10) {
// iOS 10
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
NSLog(@"greet");
} else {
NSLog(@"reject");
}
}];
} else if (DEF_IOS8) {
// iOS 8 和 iOS 9
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
} else {
// iOS 7
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound];
}
iOS9以後,每次重新安裝應用後得到的 Token
是不一樣的,而且每次重裝系統也會改變,所以 每次應用啓動時都需要按上面的步驟註冊一次
2.發送DeviceToken
application:didRegisterForRemoteNotificationsWithDeviceToken:
在這個方法裏把deviceToken
發送給服務器Provider
3.接收通知
** 應用在前臺
iOS6
-(void) application: didReceiveRemoteNotification:
iOS7 ~ iOS9
-(void) application: didReceiveRemoteNotification: fetchCompletionHandler:
iOS10
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
** 應用在後臺,但是還活着
iOS6 ~ iOS9 調用方法和應用在前臺相同
iOS10
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler
** 應用被殺死狀態
這種情況和應用重新啓動類似,應用會調用下面的方法重新啓動
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
其中,通知的信息在launchOptions
裏,
id userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]
參考資料
http://www.jianshu.com/p/ad43bc1a970a
http://www.tuicool.com/articles/AFRvemV
http://blog.csdn.net/hherima/article/details/47133171