ANCS は「Apple Notification Center Service」の略で、電話着信やメール受信等、iOSで発生するさまざまな種類の通知に、BLEで繋がっている外部デバイスからアクセスするためのサービスです。
iOSアプリに携わるエンジニアとしてはリモート通知(プッシュ通知)の APNS (Apple Push Notification Service) と混同しそうになる略称ですが、もちろん別モノです。
IoTとかウェアラブル的な文脈では大抵のケースでiOSデバイスがセントラルになり、外部デバイスがペリフェラルとなりますが、ANCSはiOSデバイスがサービス提供側となるため、その立場が逆転し、iOSデバイスがペリフェラル、外部デバイスがセントラルとなります。
※本記事はBLEアドベントカレンダー5日目の記事です。
用語について
Appleが提供しているドキュメント「Apple Notification Center Service (ANCS) Specification」では、サービス提供側(つまりiOSデバイス)を NP (Notification Provider)、サービスを受ける側(外部デバイス)を NC (Notification Consumer) と呼んでいるので、本記事でも以降そのように表現します。
また、同ドキュメントでは、iOSにおけるPush NotificationやLocal Notificationといった通知と、GATTにおけるNotificationを呼び分けるため、"iOS Notification", "GATT Notification" という表現が使用されています。本記事内でも、これらの区別のため「iOS通知」「GATT通知」という表現を使用します。
ANCS の GATT
ANCSサービスのUUIDは次のように定義されています。
7905F431-B5CE-4E99-A40F-4B1E122D00D0
そして、ANCSサービスは、以下のキャラクタリスティックを持っています。
Characteristic | UUID | Properties | |
---|---|---|---|
Notification Source | 9FBF120D-6301-42D9-8C58-25E699A21DBD |
notifiable | |
Control Point | 69D1D8F3-45E1-49A8-9821-9BBDFDAAD9D9 |
writeable with response | |
Data Source | 22EAC6E9-24D6-4BB5-BE44-B36ACE7C7BFB |
notifiable | |
Notification Source は、
- NPでのiOS通知の到着
- NPでのiOS通知の変更
- NPでのiOS通知の削除
をNCに知らせるためのキャラクタリスティックです。
また Control Point は NC が NP に iOS通知のより詳細な情報を要求するための Write キャラクタリスティックで、Control Point への書き込みが成功すると、NP は Data Source キャラクタリスティックでのGATT通知によりリクエストに応答します。
これらのサービス/キャラクタリスティックでは、別のiOSデバイスからセントラルとして接続しても見つからないようになっています。ANCSが提供されるようになったiOS7より前のiOSデバイス、あるいはそれ以外のMac等のデバイスからは見つけることができます。
実装サンプル
以下、Notification Source キャラクタリスティックを介して、iOS通知の到着や変更をNC側で受け取る実装方法について説明します。
NPの実装
NC側からペリフェラル名で発見できるように、`CBAdvertisementDataLocalNameKey` に何らかのデバイス名を指定してアドバタイズ開始しておきます。(一般的なペリフェラルマネージャの実装なのでコードは省略)
NCの実装
上述した通りiOSデバイスはNCになれないため、ここでは Mac OS X のアプリとして実装します。
なお、スキャン、接続、サービス/キャラクタリスティックの探索まではセントラルとしては通例通りの処理なので説明を省略します。
Notification Source をサブスクライブする
Notification Source キャラクタリスティックの値の更新通知を有効にします。
- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error { CBUUID *notificationSourceUuid = [CBUUID UUIDWithString:@"9FBF120D-6301-42D9-8C58-25E699A21DBD"]; for (CBCharacteristic *aCharacteristic in service.characteristics) { if ([aCharacteristic.UUID isEqualTo:notificationSourceUuid]) { self.notificationSourceCharacteristic = aCharacteristic; // Notification Source の subscribeを開始する [peripheral setNotifyValue:YES forCharacteristic:aCharacteristic]; } } }
Notification Source の値を読む
Notification Source キャラクタリスティックの値は、次のような8バイトで構成されています。
本サンプルでは、どのようなiOS通知があったのかを最低限判別できるよう、「EventID」「CategoryID」の2つを読み取ることにします。
EventIDはiOS通知が「新規」「変更」「削除」のどれなのかを示す値で、次のように定義されています。
EventIDNotificationAdded | 0 | |
EventIDNotificationModified | 1 | |
EventIDNotificationRemoved | 2 | |
Reserved EventID values | 3-255 | |
CategoryIDはiOS通知の種類を示す値で、次のように定義されています。
CategoryIDOther | 0 | |
CategoryIDIncomingCall | 1 | |
CategoryIDMissedCall | 2 | |
CategoryIDVoicemail | 3 | |
CategoryIDSocial | 4 | |
CategoryIDSchedule | 5 | |
CategoryIDEmail | 6 | |
CategoryIDNews | 7 | |
CategoryIDHealthAndFitness | 8 | |
CategoryIDBusinessAndFinance | 9 | |
CategoryIDLocation | 10 | |
CategoryIDEntertainment | 11 | |
Reserved CategoryID values | 12–255 | |
Notification Source キャラクタリスティックの値に変更があると、すなわちNP側で電話着信などのiOS通知が新規で発生した/変更された、等のイベントが発生すると、サブスクライブしているNCに対してGATT通知が送られます。
このタイミングでキャラクタリスティックからEventIDとCategoryIDを読み取り、ログ出力するコードは次のようになります。
- (void) peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error { NSLog(@"%@", characteristic.value); // 8バイト取り出す unsigned char bytes[8]; [characteristic.value getBytes:bytes length:8]; // Event ID unsigned char eventId = bytes[0]; switch (eventId) { case 0: NSLog(@"Notification Added"); break; case 1: NSLog(@"Notification Modified"); break; case 2: NSLog(@"Notification Removed"); break; default: // reserved break; } unsigned char categoryId = bytes[2]; switch (categoryId) { case 0: // Other break; case 1: NSLog(@"Incoming Call"); break; case 2: NSLog(@"Missed Call"); break; case 3: NSLog(@"Voice Mail"); break; case 4: NSLog(@"Social"); break; case 5: NSLog(@"Schedule"); break; case 6: NSLog(@"Email"); break; case 7: NSLog(@"News"); break; case 8: NSLog(@"Health and Fitness"); break; case 9: NSLog(@"Business and Finance"); break; case 10: NSLog(@"Location"); break; case 11: NSLog(@"Entertainment"); break; default: // Reserved break; } }
実行結果
次のようにログ出力されました。(見やすいよう各通知のログを1行にまとめています)
<001d0201 00000000>, Notification Added, Missed Call <001d0202 01000000>, Notification Added, Missed Call <001d0203 02000000>, Notification Added, Missed Call <00150601 03000000>, Notification Added, Email <00150602 04000000>, Notification Added, Email <00100603 05000000>, Notification Added, Email <00100604 06000000>, Notification Added, Email <00150605 07000000>, Notification Added, Email <00150401 08000000>, Notification Added, Social <00150b01 09000000>, Notification Added, Entertainment <00150b02 0a000000>, Notification Added, Entertainment <00150b03 0b000000>, Notification Added, Entertainment <00150a01 0c000000>, Notification Added, Location <00150801 0d000000>, Notification Added, Health and Fitness <00150802 0e000000>, Notification Added, Health and Fitness <00150901 0f000000>, Notification Added, Business and Finance <00150001 10000000>, Notification Added <00150002 11000000>, Notification Added <00150003 12000000>, Notification Added <00150402 13000000>, Notification Added, Social
電話着信やメール受信、SNSのiOS通知の発生や削除がNC側(ここではMacアプリ)で検知できていることがわかります。
iOSでの通知設定について
PebbleのSupport Centerのページによると、iOS側の通知をどこまで許可することでANCSによりNCに通知されるかがアプリによって違うようです。
The following apps need nothing more than "Allow Notifications" for their notifications to appear on Pebble.
- iOS 7 email
- SMS and iMessages
- Calendar
- CalenMob
- BBM
At least one of the alert styles (banners, alerts, badge app icon, or alert sound) must be enabled for the following apps, in addition to having "Allow Notifications" on.
- Gmail
- Hangouts
- Facebook Messenger
- Snapchat
The following apps require that the banners alert style specifically be chosen in order to deliver notifications to Pebble:
# 同ページでは "Here is what we have discovered so far:", "If you are aware of any other apps which require a special set up, please contact our Support Team" 等と表現されていることから、どういうルールでこれらが決まるのかははっきりしていないようです。