蘋果ANCS官網(wǎng)ANCS spec:
https://developer.apple.com/library/content/documentation/CoreBluetooth/Reference/AppleNotificationCenterServiceSpecification/Introduction/Introduction.html#//apple_ref/doc/uid/TP40013460-CH2-SW1
此文大部分內容來自官方的翻譯,加上了自己的一些蹩腳的理解。
一、簡介
ANCS是Apple Notification Center Service的簡稱,中文為蘋果通知中心服務。
ANCS是蘋果讓周邊藍牙設備(手環(huán)、手表等)可以通過低功耗藍牙訪問IOS設備(iphone、ipad等)上的各類通知提供的一種簡單方便的機制。
依賴
ANCS是基于BLE協(xié)議中的通用屬性協(xié)議(Generic Attribute Profile,GATT)協(xié)議實現(xiàn)的,他是GATT協(xié)議的一個子集。在ANCS協(xié)議中,IOS設備作為gatt-server,而周邊設備作為gatt client來連接和使用server提供的其他services。
端和字符編碼
除非特殊說明,IOS設備ANCS與ble設備進行通信的過程中都是采用的小端模式進行傳輸?shù)?,比如NC接收到的attribute length數(shù)據(jù)為0x02 0x00,應該解析為0x00 0x02,即長度為2byte.
字符串的編碼采用了UTF-8編碼格式。
相關術語
NP(Notification Provider):消息提供者,指的是ANCS服務的產(chǎn)生者,即IOS設備。
NC(Notification Consumer):消息接受者,指的是ANCS服務的客戶端,即周邊BLE設備。
二、ANCS
蘋果通知中心服務的UUID為7905F431-B5CE-4E99-A40F-4B1E122D00D0。
由于IOS的特性限制,一個蘋果設備上只能有一個ANCS存在,一個ANCS可以連接多個client。因為ANCS并不能保證始終存在(be present?),NC需要訂閱服務變更特性(the Service Changed characteristic of the GATT service )以便任何時候都可以監(jiān)聽準備發(fā)布和取消發(fā)布的ANCS。
服務特性
ANCS有三個特性:
-
Notification Source: UUID 9FBF120D-6301-42D9-8C58-25E699A21DBD
通知源,權限是可通知 -
Control Point: UUID 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9
控制點,權限是可寫入,可響應 -
Data Source: UUID 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB
數(shù)據(jù)源,權限是可通知
所有的特性需要認證(NC設備連接上NP并且完成配對和綁定)才能過連接。
對于NC來說,通知源是必須訂閱的,其他兩個是可選擇的。
通知源
NC收到的通知源特性主要有三種事件:
- NP上新通知的到達
- NP上通知的修改
- NP上通知的刪除
當NC訂閱了通知源特性時,這些通知將會立刻被分發(fā)。因此NC在訂閱該特性時必須處于有能力接收和處理這些消息的狀態(tài)。

經(jīng)過數(shù)據(jù)源特性分發(fā)的Gatt通知包含一下信息:
- EventID:這個字段指明了iOS通知添加、修改或移除三種事件中的一種。該字段的枚舉值可參考后面附錄的EventID Value表。
- EventFlags:一個位掩碼,這個位掩碼表明了這個通知的一種特征。例如,如果一個通知被認為是重要的,那么NC收到這個通知后,就想用明顯的方式提醒用戶。位掩碼的枚舉值在后面的EventFlags表中。
- CategoryID:通知的種類,分為郵件,來電,未接來電,社交,娛樂等多種分類,短信和微信扣扣等消息全部在社交(social)。
- CategoryCount:給定類型中活躍的通知的數(shù)量。例如,郵箱中有兩封未讀的郵件,這個時候又來了一封新的郵件,那么通知的郵件的數(shù)量將是3。
- NotificationUID:該通知的id,一個32位的數(shù)字來作為通知的唯一標示(UID)。獲取更多該通知的信息時,這個數(shù)值在將作為命令中的一個句柄寫入控制點特性(即告訴控制點我想要獲得那條通知的詳細信息)。

控制點和數(shù)據(jù)源
NC設備可能想要與IOS通知進行交互。它可能需要獲得通知的更多信息,其中包括它的內容以及在此基礎上進行一些操作,這些都要通過控制點和數(shù)據(jù)源特性來實現(xiàn)。
NC可以通過往控制點特性里寫入命令來獲取關于通知的更多消息。如果命令寫入成功的話,NP會在數(shù)據(jù)源特性中通過通知流對該請求進行回復。
獲取通知具體屬性的命令
獲取通知屬性命令使得NC可以得到某個特定通知的詳細屬性,比如短信的發(fā)送人,短信內容,時間等。

該命令包含了一下的信息:
- CommandID: 設為零 (CommandIDGetNotificationAttributes),0x00
- NotificationUID: 想要獲得的通知的uid,32位數(shù)字是通知的唯一標示。
- AttributeIDs:NC想要獲得的屬性列表。有些屬性可能需要后面接一個16位的的參數(shù),0xff 0xff。
byte[] getNotificationAttribute = {
//規(guī)定為0
(byte) 0x00,
//UID,通知的id
uid[0], uid[1], uid[2], uid[3],
//title,Attribute 1,第一條屬性,通知的標題
(byte) 0x01, (byte) 0xff, (byte) 0xff,
//message,第二條屬性,標題的消息
(byte) 0x03, (byte) 0xff, (byte) 0xff
};

該響應包含一下內容:
- CommandID: 設為0 (CommandIDGetNotificationAttributes)。
- NotificationUID: 32位的UID。
- AttributeList:由屬性ID、16位長度、屬性所組成的一個列表。一個屬性始終是字符串,并且它的長度由16位長度所決定,而不是以空(NULL)結束。如果所請求的屬性是空的,或者是錯過了iOS通知,那么長度設為0。
如果響應的長度大于GATT所規(guī)定的最大傳輸單元(Maximum Transmission Unit, MTU),則NP會它分成多段傳送。NC必須將響應的數(shù)據(jù)段重新組包。當收到所有請求屬性的內容時,則表示響應完成。
獲得應用屬性
獲取應用屬性命令允許NC指定獲取NP上某個已安裝的應用程序的屬性。

獲取應用屬性命令包含下面信息:
- CommandID:必須設置為1(CommandIDGetAppAttributes)。
- AppIdentifier:客戶端想要獲取信息的應用程序的字符串標志。字符串必須以空(NULL)結束。
- AttributeIDs:想要NC先要獲取的屬性列表。

響應一個獲取應用屬性命令的數(shù)據(jù)包含下面信息:
- CommandID:設置為1(CommandIDGetAppAttributes)。
- AppIdentifier:應用的字符串標識。字符串以空(NULL)結束。
- AttributeList:由屬性ID、16位長度、屬性所組成的一個列表。一個屬性始終是字符串,并且它的長度由16位長度所決定,而不是以空(NULL)結束。如果所請求的屬性是空的,或者錯過了應用應用程序,那么長度設為0。
如果響應數(shù)據(jù)的長度大于GATT所規(guī)定的最大傳輸單元(Maximum Transmission Unit, MTU),則NP會它分成多端傳送。NC必須將響應的數(shù)據(jù)段重新組包。當收到所有請求屬性的內容時,則表示響應完成。
**執(zhí)行通知動作
它允許NC向指定的iOS通知執(zhí)行一條預定動作。

一條執(zhí)行通知動作包含下面信息:
- CommandID:必須設置為2(CommandIDPerformNotificationAction)。
- NotificationUID:32位的數(shù)值。其值為要執(zhí)行動作的的iOS通知的UID。
- ActionID:NC對指定iOS通知要執(zhí)行的動作。
當發(fā)送這個命令到控制點特征后,無論發(fā)送成功或失敗,數(shù)據(jù)源特征上都不會產(chǎn)生數(shù)據(jù)。也就是說這是一個無需響應的命令。
通知動作
從iOS8開始,NP發(fā)送的iOS通知起始可以間接的告訴NC可執(zhí)行哪些動作。接著,NC就可以針對指定的iOS通知,請求NP執(zhí)行一個動作。
通知源特征上生成的GATT通知包含一個叫做Eventflags的數(shù)據(jù)域,NC根據(jù)這個數(shù)據(jù)域就可得知對一條iOS通知可以執(zhí)行哪些操作:
- EventFlagPositiveAction:積極動作(Positive Action),與iOS通知相關。
- EventFlagNegativeAction:消極動作(Negative Action),與iOS通知相關。
實際的動作都是由NP執(zhí)行的,這就表示:NC可執(zhí)行動作都是由NP所決定的,而且根據(jù)iOS通知的不同而不同。舉個例子,當NC收到來電通知時,執(zhí)行積極動作可以接聽,執(zhí)行消極動作就拒接,而對于消息(官方是social)類型的通知而言,則只有消極操作,也就是說,在手表等從設備上面只能查看消息,而無法回復。
NC不能預先去假設或嘗試猜測一條iOS通知確切的可執(zhí)行的動作。因為這些動作都是基于特定通知的,只有NP知道,而對NC無用的;同時還有其它的因素,如ANCS版本的變化等。這樣,NP才能保證積極動作和消極動作的結果都與用戶沒多大關系。
iOS 8系統(tǒng)中,NC通過發(fā)送獲取通知屬性命令,可獲取到某條iOS通知可執(zhí)行動作的簡潔描述:
- NotificationAttributeIDPositiveActionLabel:這條標簽用于描述某條iOS通知可執(zhí)行的積極動作。
- NotificationAttributeIDNegativeActionLavel:這條標簽用于描述某條iOS通知可執(zhí)行的消極動作。
三、生命周期
一個ANCS的服務周期開始于NC訂閱NP上的Notification Source characteristic,結束于NC取消該訂閱或者斷開連接。因為ANCS不是一種完全同步的服務,它沒有追蹤不同周期中的狀態(tài),因此所有的標示以及NC、NP之間的數(shù)據(jù)交換只在某一個周期中是有效的。
當一個周期結束后,NC應該刪除其在本周期內采集和存儲的所有的標示以及數(shù)據(jù)。一個新的周期開始的時候,NP會可能的把所有存在的通知下發(fā)給NC。
四、錯誤碼
當往 Control Point characteristic中寫入控制命令時,NC有時會受到ANCS錯誤碼:
Unknown command (0xA0): 命令無法識別.
Invalid command (0xA1): 命令格式錯誤.
Invalid parameter (0xA2): 參數(shù)錯誤,例如notification uid并不存在對應的notification對象.
Action failed (0xA3): 動作沒有被執(zhí)行。
如果NP回復了一個錯誤碼,那么Data Source characteristic中將不再產(chǎn)生任何回應的命令的數(shù)據(jù)。
五、示例圖
以下兩個圖展示了NP和NC之間的兩種交互的過程的例子。Figure 2-7顯示了NC上想要開啟ANCS的基本流程;Figure 2-8 展示了NC獲得IOS通知更多信息的基本流程。
Figure 2-7 Service setup example
Figure 2-8 Notification attribute retrieval example