綜述
蘋果通知中心(Apple Notification Center Service, ANCS)的目的是提供給藍牙外設一種簡單、方便的獲取ios設備通知信息的方式。
依賴
ANCS的使用沒有依賴,它是GATT的一個子集,任何一個實現了GATT client的設備可以方便的從ios設備獲取通知信息。
傳輸注意事項
如果沒有特殊說明,通過ANCS傳輸的數值均使用小端模式。
如果沒有特殊說明,通過ANCS傳輸的字符串均使用UTF-8編碼。
概念定義
l ANCS:蘋果通知中心服務
l NP(Notification Provider):通知的產生者,一般是ios設備
l NC(Notification Consumer):通知的消費者,一般是藍牙設備
l iOS notification:ios設備里出現的通知
l GATT notification:GATT characteristic發送的通知
Service定義
ANCS使用了一個私有UUID作為其Service的UUID:
7905F431-B5CE-4E99-A40F-4B1E122D00D0
NP上只有一個ANCS實例,基於ios的機制,ANCS沒有辦法保證一直運行。
所以NC需要搜索並且監聽(subscribe)Service Changed characteristic,以保證能夠堅挺到所有通知。
(怎么做。。。。Service Changed characteristic是啥)
Characteristic類型
所涉及的characteristic
1、Notification Source:
UUID 9FBF120D-6301-42D9-8C58-25E699A21DBD(notifiable)
基本通知源,通知一些計數的信息;
2、Control Point:
UUID 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9(writeablewithresponse)
控制器,用於向ios設備寫入控制信息,例如讀取詳情;
3、Data Source:
UUID 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB(notifiable)
數據源,用於提供詳細數據,在控制信息寫入后通過此characteristic返回;
還有許多其他characteristic,不過只有Notification Source是強制的,其他的都是可選的。
Notification Source
通知信息更新時,從NP發給NC的消息。
有以下一些情況:
l 新的ios通知到來;
l ios通知有改動;
l ios通知移除;
l EventID:消息類型,添加(0)、修改(1)、刪除(2);
l EventFlags:消息優先級,靜默(1)、重要(2);
l CategoryID:消息類型;
l CategoryCount:消息計數;
l NotificationUID:通知ID,可以通過此ID獲取詳情;
Notification的生命周期如下:
Get Notification Attributes
當NC希望從NP讀取Notification的詳細信息時,它需要向Control Point characteristic發送一些命令,格式如下:
l CommandID:設為0;
l NotificationUID:對應Notification Source中相同名字的字段;
l AttributeIDs:NC希望讀取的變量ID列表,有些變量可能需要跟一個16bit的數說明想要的最大長度;
NP接收到此命令后,會通過Data Source characteristic將結果返回(通過GATT Notification),所以你需要監聽這個參數。此命令發出后對應的返回信息如下:
l CommandID:為0;
l NotificationUID:對應之前請求的UID;
l AttributeList:查詢結果列表,每一項的格式都是:ID/16bit Length/Value,每個attribute都是一個字符串,其長度由Length指定,但是此字符串不是以NULL結尾。若找不到對應的Attribute,則Length為0;
* 如果返回的消息長度大於GATT最大傳輸長度(MTU),則其會被分割成多個分段。藍牙設備必須將這些分段組裝起來。當所有請求屬性的內容都接收完成后,此過程才算完成;
Get App Attributes
此命令允許NC讀取NP上安裝app的特定屬性,它需要向Control Point characteristic發送一些命令,格式如下:
l CommandID:設成1;
l AppIdentifier:App ID,這個字符串必須使用NULL結尾(“\0”吧);
l AttributeIDs:希望獲得屬性的列表;
此命令的響應消息格式如下:
l CommandID:為1;
l AppIdentifier:App ID,與之前的請求ID對應;
l AttributeList:屬性值列表,每一個格式都是:ID/16-bit Length/Value,每個attribute都是一個字符串,其長度由Length指定,但是此字符串不是以NULL結尾。若找不到對應的Attribute,則Length為0;
* 關於分段以及傳輸結束的判斷標准,與Get Notification Attributes一致;
Session(會話)
ANCS session 在NC訂閱Notification Source之后開始,在取消訂閱或者連接斷開之后結束。由於ANCS不是一個完全同步的服務,它不會在會話中記錄狀態。所以,所有的NotificationUID以及AppIdentifier僅在某個特定的會話周期內有效。(換句話說,那些ID只是在會話后開始的計數,下次再連接重新計數)
當某個會話結束時,NC需要清空所有ID以及數據內容。當新的會話開始時,NP會盡量把現有的通知都發給NC。NC可以使用這些信息知道當前尚未處理的通知有哪些。
Attribute Fetching and Caching
我們建議,只在用戶做出操作時才獲取attribute。例如,一開始只是展示一個通知列表,然后在用戶點擊某一個后才查詢詳細的信息。
另外,我們建議在一次會話中建立一張App attribute的緩存表,這樣可以避免重復獲取一些常量attribute。
Error Codes
寫入Control Point characteristic時,可能會有錯誤發生,錯誤碼定義如下(在哪里返回錯誤碼。。。同一次請求中么):
0xA0 : 未知命令,commandID非法;
0xA1 : 無效命令,命令的格式錯誤;
0xA2 : 無效參數,某一個參數(例如NotificationID無效)
如果有錯誤發生,就不會有Data Source返回。
時序圖
下面展示了NP與NC之間的常見交互時序:
下面的圖展示了獲取詳細信息的時序:
CategoryID
EventID
EventFlags
CommandID
NotificationAttributeID
AppAttributeID
實際實驗之DataSource讀取
主要是介紹一下讀取的各個AttrID返回的都是啥:
電話:
AttrID |
返回值 |
0(App ID) |
com.apple.mobilephone |
1(Title) |
1 (326) 021-3971(電話號碼,不過划分方式好怪。。。) 如果此號碼存了名字,則是電話本中的名字 |
2(SubTitle) |
空 如果此號碼存了名字,則是mobile |
3(Message) |
Incoming Call |
短信:
AttrID |
返回值 |
0(App ID) |
com.apple.MoileSMS |
1(Title) |
10698109555991 01051726663 +86 132-6021-3971 如果此號碼存了名字,則是電話本中的名字 |
2(SubTitle) |
空 |
3(Message) |
短信的內容 |
微信:
AttrID |
返回值 |
0(App ID) |
com.tencent.xin |
1(Title) |
微信 |
2(SubTitle) |
空 |
3(Message) |
發信人:內容 |