core bluetoothプログラミングガイド (tp40013257 0.0.0)

53
Core Bluetooth プログラミングガイド

Upload: dinhdang

Post on 28-Jan-2017

236 views

Category:

Documents


10 download

TRANSCRIPT

Page 1: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothプログラミングガイド

Page 2: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

目次

Core Bluetoothについて 5はじめに 5

Core Bluetoothではセントラルとペリフェラルが重要な役割を果たす 5Core Bluetoothを導入すれば、Bluetoothを扱う上で常に必要となるタスクを簡単に実装できる

6iOSアプリケーションの状態によってBluetoothの挙動が変わる 6使い勝手を改善するためのベストプラクティスに従う 7

この文書の使い方 7関連項目 7

Core Bluetoothの概要 9セントラルとペリフェラルのBluetooth通信における役割 9セントラルは、アドバタイズしているペリフェラルを検出し、接続する 10ペリフェラルのデータはどのような構造になっているか 10セントラルはペリフェラルがどのようなデータを提供するか調査し、実際にやり取りする 11

セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するか 11セントラル側のオブジェクト 12ペリフェラル側のオブジェクト 13

セントラルが実行するタスク 15セントラルマネージャを起動する 15アドバタイズしているペリフェラルを検出する 16検出したペリフェラルに接続する 17接続したペリフェラルのサービスを検出する 18サービスの特性を検出する 18特性の値を取得する 19特性の値を読み取る 19特性の値が変化したときに通知するよう申し込む 20

特性値を書き込む 21

ペリフェラルが実行するタスク 23ペリフェラルマネージャを起動する 23サービスおよび特性をセットアップする 24サービスや特性はUUIDで識別する 24

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

2

Page 3: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

独自のサービスや特性を識別するUUIDを生成する 24サービスおよび特性の木を構築する 25

サービスや特性を登録する 26サービスをアドバタイズする 27セントラルからの読み書き要求に応答する 28特性値が変化したとき、あらかじめ申し込まれているセントラルに通知する 30

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用) 32フォアグラウンド動作のみのアプリケーション 32ペリフェラル接続オプションを活用する 33

Core Bluetoothのバックグラウンド実行モード 33バックグラウンド実行モード「bluetooth-central」 34バックグラウンド実行モード「bluetooth-peripheral」 35

バックグラウンド実行モードを適切に活かす 35長時間にわたるアクションをバックグラウンドで実行する 36状態の保存と復元 36状態の保存/復元機能を組み込む 37

リモートのペリフェラルとのやり取りに関するベストプラクティス 42電波の使い方や電池の寿命に注意を払う 42デバイスの走査は必要な場合にのみ行う 42必要がなければCBCentralManagerScanOptionAllowDuplicatesKeyオプションを指定しない 42ペリフェラルのデータを的確に調査する 43頻繁に変化する特性については、値の変化を通知するよう申し込む 43必要なデータがすべて得られたら切断する 44

ペリフェラルに再接続する 44既知のペリフェラルのリストを取得する 46接続済みペリフェラルのリストを取得する 47

ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス 48アドバタイズに関する検討事項 48アドバタイズするデータの制限事項を考慮する 48必要のないデータはアドバタイズしない 49

特性を設定する 49通知の申し込みに対応できるよう特性を設定する 50重要なデータについて、ペアリングした機器からのアクセスのみを許可する 50

書類の改訂履歴 52

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

3

目次

Page 4: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothの概要 9図 1-1 セントラルとペリフェラル 9図 1-2 アドバタイズとその検出 10図 1-3 ペリフェラルのサービスと特性 11図 1-4 セントラル側にあるCore Bluetoothのオブジェクト 12図 1-5 リモートのペリフェラルが提供する、サービスや特性が成す木 13図 1-6 ペリフェラル側にあるCore Bluetoothのオブジェクト 14図 1-7 ローカルのペリフェラルが提供する、サービスや特性が成す木 14

リモートのペリフェラルとのやり取りに関するベストプラクティス 42図 5-1 再接続処理の流れの例 45

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

4

Page 5: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothフレームワークには、iOS/Macアプリケーションが、Bluetooth Low Energy(BLE)という省電力無線通信技術を実装したデバイスと通信するために必要なクラス群があります。アプリケーションは、心拍モニタ、デジタルサーモスタットなどの周辺機器(ペリフェラル)を検出、調査し、情報をやり取りできることになります。OS X v10.9およびiOS 6以降、Mac/iOSデバイス自身もBLEペリフェラルとして機能し、他のデバイス(Mac/iOSデバイスを含む)にデータを提供できるようになりました。

はじめにBLEという省電力無線通信技術は「Bluetooth 4.0」仕様に基づいています。省電力デバイス間で通信するための、各種プロトコルを定義している仕様です。Core Bluetoothフレームワークは、BLEプロトコルスタックを抽象化しています。仕様のうち低階層に当たる詳細を隠蔽して、BLE機器とデータをやり取りするアプリケーションを、容易に開発できるようにしているのです。

Core Bluetoothではセントラルとペリフェラルが重要な役割を果たすBLE通信には、セントラル(中央装置、Centrals)とペリフェラル(周辺装置、Peripherals)が関与します。両者はそれぞれ異なる役割を担います。ペリフェラルには通常、他のデバイスが必要とするであろうデータがあります。セントラルは、ペリフェラルから提供される情報を使って、何らかのタスクを実行します。たとえばBLE技術搭載デジタルサーモスタットは、室温データをiOSアプリケーションに提供します。アプリケーションはこのデータを見やすく表示します。

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

5

Core Bluetoothについて

Page 6: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

それぞれの役割の違いに応じて、実行するタスクも異なります。ペリフェラルは自身の存在を知らしめるため、電波を使って周囲に「広告」を出します(「アドバタイズ」と言います)。一方、セントラルは、必要なデータを提供してくれるペリフェラルがないか走査します。該当するペリフェラルを検出すると、接続を要求し、データのやり取りを始めます。一方、ペリフェラルは適切な方法で、セントラルに応答します。

関連する章: “Core Bluetoothの概要” (9 ページ)

Core Bluetoothを導入すれば、Bluetoothを扱う上で常に必要となるタスクを簡単に実装できるCore Bluetoothフレームワークは、Bluetooth 4.0仕様のうち低階層にあたる詳細を隠蔽(抽象化)しています。したがって、BLEを扱う上で必要となるさまざまなタスクを、簡単にアプリケーションに実装できるのです。セントラルとして動作するアプリケーションを開発する場合、ペリフェラルを検出、接続し、データをやり取りする処理を容易に記述できます。また、ローカルデバイスをペリフェラルとして動作させるのも容易です。

関連する章: “セントラルが実行するタスク” (15 ページ)、“ペリフェラルが実行するタスク” (23 ページ)

iOSアプリケーションの状態によってBluetoothの挙動が変わるiOSアプリケーションがバックグラウンド状態や一時停止状態になると、Bluetoothに関わる挙動が変わります。通常、この状態ではBLEタスクを実行できないのです。バックグラウンド状態でも実行できるようにするためには、Core Bluetoothのバックグラウンド実行モード(セントラルとしての役割、ペリフェラルとしての役割があり、その一方または両方)に対応する旨、宣言しなければなりません。宣言した場合でも、タスクによっては、バックグラウンド状態になると動作が変わります。アプリケーションの設計時に、この違いを考慮しなければなりません。

バックグラウンド状態で実行できる場合でも、システムがいつでも強制的に停止する可能性があります。メモリを解放し、フォアグラウンドアプリケーションに割り当てるためです。iOS 7以降、セントラル/ペリフェラルマネージャオブジェクトの状態を保存しておき、次のアプリケーション起動時に復元できるようになりました。この機能を活用すれば、長時間にわたるアクションも実装できます。

Core Bluetoothについてはじめに

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

6

Page 7: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

関連する章: “Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)” (32 ページ)

使い勝手を改善するためのベストプラクティスに従うCore Bluetoothフレームワークを利用すれば、BLEトランザクションの多くを、アプリケーションが制御できるようになります。ユーザにとっての使い勝手を考慮し、適切に制御しなければなりません。

たとえば、セントラルもペリフェラルも、さまざまなタスクのために、周囲に電波信号を送出します。各種の無線通信機器が同じ周波数帯を共有しており、また、電池の寿命にも悪影響があるので、送信を最小限に抑えるようアプリケーションを設計してください。

関連する章: “リモートのペリフェラルとのやり取りに関するベストプラクティス” (42 ページ)、“ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス” (48 ページ)

この文書の使い方初めてCore Bluetoothフレームワークを使うか、そうでなくてもBLEの基本的な考え方になじんでいない方は、この資料全体に目を通してください。“Core Bluetoothの概要” (9 ページ)では、読み進めるために必要となる用語や概念を説明します。

基本的な考え方を頭に入れたら、“セントラルが実行するタスク” (15 ページ)を読んで、ローカルデバイスをセントラルとして扱うアプリケーションの実装方法を身につけてください。同様に、ペリフェラルとして扱うアプリケーションについては、“ペリフェラルが実行するタスク” (23 ページ)で説明します。

ベストプラクティスに基づき、アプリケーションが良好に動作するよう、“Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)” (32 ページ)、“リモートのペリフェラルとのやり取りに関するベストプラクティス” (42 ページ)、“ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス” (48 ページ)も読んでおくとよいでしょう。

関連項目Bluetooth Special Interest Group(SIG)の公式ウェブサイトには、BLE技術に関する、最も信頼できる情報が集まっています。ここにはBluetooth 4.0の仕様文書もあります。

Core Bluetoothについてこの文書の使い方

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

7

Page 8: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

BLE技術を使ってApple製品(Mac、iPhone、iPad、iPod touchなど)と通信するハードウェア機器を設計する際には、『Bluetooth Accessory Design Guidelines for Apple Products』を参照してください。さらに、このBLE機器がiOSデバイスと接続し、iOSデバイスが生成する通知にアクセスできるようにしたい場合は、『Apple Notification Center Service (ANCS) Specification』を参照してください。

Core Bluetoothについて関連項目

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

8

Page 9: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothフレームワークには、iOS/MacアプリケーションがBLEデバイスと通信できるようにする働きがあります。心拍モニタ、デジタルサーモスタット、あるいは他のiOSデバイスなどのペリフェラルを検出、調査し、情報をやり取りできるようになるのです。

フレームワークは、Bluetooth 4.0仕様に定義されているBluetooth通信の、細かな挙動を抽象化しています。仕様のうち低階層に当たる詳細を隠蔽して、BLE機器とデータをやり取りするアプリケーションを、容易に開発できるようにしているのです。フレームワークは上記の仕様に基づいているので、基本的な概念や用語も仕様に沿ったものになります。この章では、Core Bluetoothフレームワークを使ってアプリケーションを開発する際に知っておくべき、重要な用語や概念について説明します。

セントラルとペリフェラルのBluetooth通信における役割BLE通信には、セントラルとペリフェラルが関与します。やや伝統的とも言えるクライアント/サーバ型アーキテクチャが基盤となっており、ペリフェラル(periferal)には通常、他のデバイスが必要とするであろうデータがあります。一方、セントラル(central)は、ペリフェラルから提供される情報を使って、何らかのタスクを実行します。図 1-1のように、たとえば心拍モニタには有用なデータがあり、Mac/iOSアプリケーションはこれを見やすく加工して表示します。

図 1-1 セントラルとペリフェラル

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

9

Core Bluetoothの概要

Page 10: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

セントラルは、アドバタイズしているペリフェラルを検出し、接続するペリフェラルはアドバタイズパケットの形式で、所定のデータを同報送信(broadcast)します。アドバタイズパケット(advertising packet)は比較的小さなデータバンドルで、ペリフェラルの名前や主な機能など、提供可能なデータを表す情報が入っています。たとえばデジタルサーモスタットは、現在の室温データを提供できる旨アドバタイズします。BLEではアドバタイズが、ペリフェラルが自身の存在を他の機器に知らしめるための、重要な手段になっています。

一方、セントラルは、必要なデータを提供してくれるペリフェラルがないか走査します(図 1-2を参照)。アドバタイズを検出したセントラルは、送出元のペリフェラルに対して接続を要求できます。

図 1-2 アドバタイズとその検出

ペリフェラルのデータはどのような構造になっているかペリフェラルに接続する目的は、どのようなデータが提供されるか調査し、そのデータをやり取りすることです。しかしこの話の前に、ペリフェラルのデータがどのような構成になっているか説明しておきましょう。

ペリフェラルは、1つ以上のサービス(あるいは接続信号強度に関する有用な情報)を提供します。サービス(service)とは、デバイス(またはその一部)の目的を達成するためのデータと、これに関連する動作をまとめて呼ぶ用語です。たとえば心拍モニタには、心拍センサーから取得した心拍データを提供する、というサービスがあります。

Core Bluetoothの概要セントラルとペリフェラルのBluetooth通信における役割

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

10

Page 11: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

サービス自身は、特性またはサービスから成ります(後者は別のサービスを参照する形で構成)。特性(characteristic)とは、ペリフェラルのサービスに関する詳細です。たとえば先に述べた心拍サービスは、心拍センサーが体のどの位置にあるかを表す特性、心拍測定データを送信する特性などから成ります。図 1-3に、心拍モニタのサービスと特性の構成(例)を示します。

図 1-3 ペリフェラルのサービスと特性

セントラルはペリフェラルがどのようなデータを提供するか調査し、実際にやり取りするセントラルは、ペリフェラルとの接続を確立した後、提供されるサービスおよび特性に関する情報全体を取得します(アドバタイズのデータはその一部でしかないこともあります)。

さらに、特性の値を読み書きする、という形で、ペリフェラルのサービスとやり取りすることも可能です。たとえばデジタルサーモスタットの場合、現在の室温を読み取るほか、設定温度(何度に調整するか)の値を書き込むことができるかも知れません。

セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するかBLE通信に関与する2つの機器やデータを、Core Bluetoothフレームワークは非常に分かりやすい形で表します。

Core Bluetoothの概要セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するか

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

11

Page 12: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

セントラル側のオブジェクトローカル側のセントラルを使って、リモート側のペリフェラルと情報をやり取りする場合、BLE通信のセントラル側で、所定のアクションを実行することになります。ローカル側にペリフェラルを置いてセントラルからの要求に応答する場合を除き、Bluetoothトランザクションの多くはセントラル側で行います。

アプリケーションにセントラルとしての役割を実装する方法については、“セントラルが実行するタスク” (15 ページ)および“リモートのペリフェラルとのやり取りに関するベストプラクティス” (42 ページ)を参照してください。

ローカルのセントラルとリモートのペリフェラルセントラル側では、ローカルのセントラルをCBCentralManagerオブジェクトで表します。このオブジェクトは、検出し、接続したリモートのペリフェラル(CBPeripheralオブジェクトで表す)を管理するために使います。アドバタイズしているペリフェラルを走査し、検出し、見つかった機器に接続する、などといった処理です。図 1-4に、ローカルのセントラル、リモートのペリフェラルを、CoreBluetoothフレームワークでどのように表現するか、を示します。

図 1-4 セントラル側にあるCore Bluetoothのオブジェクト

Core Bluetoothの概要セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するか

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

12

Page 13: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

リモートのペリフェラルが持つデータはCBServiceおよびCBCharacteristicオブジェクトで表現するリモートのペリフェラル(CBPeripheralオブジェクトで表す)が持つデータをやり取りするとき、実際に操作しているのはそのサービスや特性です。Core Bluetoothフレームワークでは、リモートのペリフェラルが提供するサービスをCBServiceオブジェクトで表します。同様に、このサービスの特性をCBCharacteristicオブジェクトで表現します。図 1-5に、リモートのペリフェラルが提供するサービスや特性の、基本的な構成を示します。

図 1-5 リモートのペリフェラルが提供する、サービスや特性が成す木

ペリフェラル側のオブジェクトOS X v10.9およびiOS 6以降、Mac/iOSデバイス自身もBLEペリフェラルとして機能し、他のデバイス(Mac、iPhones、iPadsを含む)にデータを提供できるようになりました。デバイスにペリフェラルとしての役割を実装する場合、BLE通信のペリフェラル側で、所定のアクションを実行することになります。

ローカルのペリフェラルとリモートのセントラルペリフェラル側では、ローカルのペリフェラルをCBPeripheralManagerオブジェクトで表します。このオブジェクトは、ローカルのペリフェラルが提供するサービス/特性のデータベースを管理し、リモートのセントラル(CBCentralオブジェクトで表す)に対してこのサービスをアドバタイズする

Core Bluetoothの概要セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するか

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

13

Page 14: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

ために使います。また、リモートのセントラルからデータの読み書き要求があったとき、これに応答するためにも使います。図 1-6に、ローカルのペリフェラル、リモートのセントラルを、Core Bluetoothフレームワークでどのように表現するか、を示します。

図 1-6 ペリフェラル側にあるCore Bluetoothのオブジェクト

ローカルのペリフェラルが持つデータはCBMutableServiceおよびCBMutableCharacteristicオブジェクトで表すローカルのペリフェラル(CBPeripheralManagerオブジェクトで表す)が持つデータをやり取りするとき、実際に操作しているのはそのサービスや特性です。Core Bluetoothフレームワークでは、ローカルのペリフェラルが提供するサービスをCBMutableServiceオブジェクトで表します。同様に、このサービスの特性をCBMutableCharacteristicオブジェクトで表現します。図 1-7に、ローカルのペリフェラルが提供するサービスや特性の、基本的な構成を示します。

図 1-7 ローカルのペリフェラルが提供する、サービスや特性が成す木

ローカルデバイスにペリフェラルとしての役割を実装する方法については、“ペリフェラルが実行するタスク” (23 ページ)および“ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス” (48 ページ)を参照してください。

Core Bluetoothの概要セントラル、ペリフェラル、ペリフェラルのデータをどのように表現するか

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

14

Page 15: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

BLE通信におけるセントラルとしての役割を実装したデバイスには、ほとんど常に必要となるさまざまなタスクがあります。ペリフェラルを検出し、接続する、ペリフェラルが提供するデータを調査し、やり取りするなどのタスクです。一方、ペリフェラルとして動作するデバイスにも多くのタスクが必要ですが、その内容は違います。サービスを公開、アドバタイズする、セントラルからの要求(読み書き、値の変化を通知するよう申し込み)に応答する、などのタスクです。

この章では、セントラル側で実行する主なタスクについて、Core Bluetoothフレームワークを使って実装する方法を説明します。ローカルデバイスにセントラルとしての役割を与えるアプリケーションを開発する際、以下に示すコード例が参考になるでしょう。具体的には次のようなタスクです。

● セントラルマネージャオブジェクトを起動する

● アドバタイズしているペリフェラルを検出、接続する

● 接続先のペリフェラルがどのようなデータを提供するか調査する

● ペリフェラルのサービスの特性値に対する読み書き要求を送信する

● 特性値が変化したときに通知するよう、ペリフェラルに申し込む

次の章では、ローカルデバイスにペリフェラルとしての役割を与えるアプリケーションの開発方法を説明します。

この章に示すコード例は簡略化してあり、そのまま実際のアプリケーションに組み込むことはできません。セントラルとしての役割の実装に関するさらに進んだ話題(ヒント、技法、ベストプラクティス)を、章を改めて解説します。“Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)” (32 ページ)および“リモートのペリフェラルとのやり取りに関するベストプラクティス” (42 ページ)を参照してください。

セントラルマネージャを起動するCBCentralManagerはローカルのセントラルを表すCore Bluetoothのオブジェクトなので、BLEトランザクションを実行するためには、そのインスタンスを生成、初期化しなければなりません。これは次のように、CBCentralManagerクラスのinitWithDelegate:queue:options:メソッドで行います。

myCentralManager =

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

15

セントラルが実行するタスク

Page 16: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

[[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];

ここではselfを、セントラルとしての役割に関係するイベントを受け取る、デリゲートオブジェクトとして設定しています。ディスパッチキューとしてnilを指定しているので、セントラルマネージャはイベントのディスパッチ用に、メインキューを使います。

セントラルマネージャは生成された後、デリゲートオブジェクトのcentralManagerDidUpdateState:

メソッドを呼び出します。このメソッドを、当該セントラルでBLEが機能するように実装してください。実装方法について詳しくは、『CBCentralManagerDelegate Protocol Reference』を参照してください。

アドバタイズしているペリフェラルを検出するセントラル側でまず実行するタスクは、多くの場合、接続可能なペリフェラルの検出でしょう。“セントラルは、アドバタイズしているペリフェラルを検出し、接続する” (10 ページ)で説明したように、アドバタイズはペリフェラルが自身の存在を他の機器に知らしめる重要な手段です。アドバタイズしているペリフェラルは、CBCentralManagerクラスのscanForPeripheralsWithServices:options:メソッドで検出できます。

[myCentralManager scanForPeripheralsWithServices:nil options:nil];

注意: 第1引数にnilを指定すれば、提供するサービスにかかわらず、検出したペリフェラルをすべて返すようになります。実際のアプリケーションでは、サービスのUUID(汎用一意識別子、Universally Unique IDentifier)を表す、CBUUIDオブジェクトの配列を指定するとよいでしょう。この場合、該当するサービスをアドバタイズしているペリフェラルのみが返されるので、走査する範囲を絞り込めます。

UUIDおよびこれを表すCBUUIDオブジェクトについて詳しくは、“サービスや特性はUUIDで識別する” (24 ページ)を参照してください。

scanForPeripheralsWithServices:options:メソッドでペリフェラルを検出すると、セントラルマネージャは見つかったペリフェラルそれぞれについて、デリゲートオブジェクトのcentralManager:didDiscoverPeripheral:advertisementData:RSSI:メソッドを呼び出します。このとき、ペリフェラルがCBPeripheralオブジェクトの形で渡されます。このデリゲートメソッドを次のように実装すれば、見つかったペリフェラルの名前を順に出力できます。

- (void)centralManager:(CBCentralManager *)central

セントラルが実行するタスクアドバタイズしているペリフェラルを検出する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

16

Page 17: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

didDiscoverPeripheral:(CBPeripheral *)peripheral

advertisementData:(NSDictionary *)advertisementData

RSSI:(NSNumber *)RSSI {

NSLog(@"Discovered %@", peripheral.name);

...

接続先のペリフェラルが見つかったら、省電力のため、他のペリフェラルの走査は停止してください。

[myCentralManager stopScan];

NSLog(@"Scanning stopped");

検出したペリフェラルに接続する必要なサービスをアドバタイズしているペリフェラルが見つかれば、次に接続を要求することになります。これはCBCentralManagerクラスのconnectPeripheral:options:メソッドで行います。接続先のペリフェラルを引数として、次のように呼び出すだけです。

[myCentralManager connectPeripheral:peripheral options:nil];

接続に成功した場合、セントラルマネージャはデリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを呼び出します。たとえば次のように実装すれば、接続が確立した旨のログが出力されるようになります。

- (void)centralManager:(CBCentralManager *)central

didConnectPeripheral:(CBPeripheral *)peripheral {

NSLog(@"Peripheral connected");

...

ペリフェラルとのやり取りを始める前に、当該ペリフェラルのデリゲートを設定してください。イベントに応じ、コールバックとしてそのメソッドが呼び出されるようになります。

peripheral.delegate = self;

セントラルが実行するタスク検出したペリフェラルに接続する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

17

Page 18: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

接続したペリフェラルのサービスを検出するペリフェラルとの接続が確立したので、次にどのようなデータが提供されるか調査します。まず、サービスの検出を行います。アドバタイズはデータ量に制限があるので、アドバタイズパケット中にはなかったサービスが見つかる可能性もあります。ペリフェラルが提供するサービスすべてのリストは、CBPeripheralクラスのdiscoverServices:メソッドで取得できます。

[peripheral discoverServices:nil];

注意: 実際のアプリケーションでは、引数としてnilを指定し、提供するサービスをすべて取得することは避けてください。不要なサービスが多数見つかる場合、電池と時間が無駄になってしまいます。必要なサービスのUUIDを具体的に指定するとよいでしょう(“ペリフェラルのデータを的確に調査する” (43 ページ)を参照)。

該当するサービスが見つかると、ペリフェラルマネージャ(接続先を表すCBPeripheralオブジェクト)は、デリゲートオブジェクトのperipheral:didDiscoverServices:メソッドを呼び出します。引数としてCBServiceオブジェクトの配列が渡されます。配列の各要素が、検出したサービスを表します。検出したサービスの配列にアクセスする、デリゲートメソッドのコード例を示します。

- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverServices:(NSError *)error {

for (CBService *service in peripheral.services) {

NSLog(@"Discovered service %@", service);

...

}

...

サービスの特性を検出する必要なサービスが見つかったら、次にその特性をすべて検出します。次のように、該当するサービスを指定して、CBPeripheralクラスのdiscoverCharacteristics:forService:メソッドを実行するだけです。

NSLog(@"Discovering characteristics for service %@", interestingService);

[peripheral discoverCharacteristics:nil forService:interestingService];

セントラルが実行するタスク接続したペリフェラルのサービスを検出する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

18

Page 19: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

注意: 実際のアプリケーションでは、引数としてnilを指定し、当該サービスの特性をすべて取得することは避けてください。不要な特性が多数見つかる場合、電池と時間が無駄になってしまいます。必要な特性のUUIDを具体的に指定するとよいでしょう。

指定されたサービスの特性を検出すると、ペリフェラルマネージャは、デリゲートオブジェクトのperipheral:didDiscoverCharacteristicsForService:error:メソッドを呼び出します。引数としてCBCharacteristicオブジェクトの配列が渡されます。配列の各要素が、検出した特性を表します。検出した特性をログに出力する、デリゲートメソッドのコード例を示します。

- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverCharacteristicsForService:(CBService *)service

error:(NSError *)error {

for (CBCharacteristic *characteristic in service.characteristics) {

NSLog(@"Discovered characteristic %@", characteristic);

...

}

...

特性の値を取得するそれぞれの特性には、サービスに関する「値」がひとつ対応しています。たとえば体温計サービスの「体温」特性には、摂氏で測った温度の値が対応している、といった具合です。特性の値は、直接読み取るか、値が変化したときに通知するよう申し込むことにより取得できます。

特性の値を読み取る該当するサービスの特性を指定して、CBPeripheralクラスのreadValueForCharacteristic:メソッドを実行することにより、その値を取得できます。

NSLog(@"Reading value for characteristic %@", interestingCharacteristic);

[peripheral readValueForCharacteristic:interestingCharacteristic];

値の読み取りが終了すると、ペリフェラルマネージャは、デリゲートオブジェクトのperipheral:didUpdateValueForCharacteristic:error:メソッドを呼び出します。読み取りに成功した場合、特性のvalueプロパティとして値を取得できます。

セントラルが実行するタスク特性の値を取得する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

19

Page 20: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

NSData *data = characteristic.value;

// 必要に応じて値をパース

...

注意: 特性の値がすべて読み取り可能とは限りません。これは、特性プロパティの、CBCharacteristicPropertyRead定数で表されるビットを参照することにより判断できます(『CBCharacteristicClassReference』を参照)。読み取り不可の値を読み取ろうとすると、デリゲートオブジェクトのperipheral:didUpdateValueForCharacteristic:error:メソッドには、error引数を通してその旨のエラーコードが渡されます。

特性の値が変化したときに通知するよう申し込むreadValueForCharacteristic:メソッドで特性値を取得すれば充分なこともありますが、値が変化しうる場合、この方法では非効率化も知れません。特性値の多くは、(たとえば心拍数のように)時間とともに変化するので、その都度通知するよう申し込んでおく、という方法があります。すると、値が変化したとき、ペリフェラルから通知が届くようになります。

申し込みは、CBPeripheralクラスのsetNotifyValue:forCharacteristic:メソッドを、第1引数にYESを指定して呼び出すことにより行います。

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

申し込み(またはその解除)を行うと、ペリフェラルマネージャは、デリゲートオブジェクトのperipheral:didUpdateNotificationStateForCharacteristic:error:メソッドを呼び出します。申し込みに失敗したとき、その原因を出力するコード例を示します。

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

if (error) {

NSLog(@"Error changing notification state: %@",

セントラルが実行するタスク特性の値を取得する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

20

Page 21: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

[error localizedDescription]);

}

...

注意: 特性がすべて、この申し込みを受け付けるとは限りません。これは、特性プロパティの、Characteristic Properties列挙子で定義されている所定のビットを参照することにより判断できます(詳しくは『CBCharacteristic Class Reference』を参照)。

申し込みに成功すれば、値が変化する都度、ペリフェラルがアプリケーションに通知を送るようになります。するとペリフェラルマネージャは、デリゲートオブジェクトのperipheral:didUpdateValueForCharacteristic:error:メソッドを呼び出します。“特性の値を読み取る” (19 ページ)と同様にこのメソッドを実装すれば、新しい値を取得できます。

特性値を書き込む用途によっては、特性値を書き込むことにも意味があるでしょう。たとえばデジタルサーモスタットとBLEでやり取りする場合、設定温度(何度に調整するか)の値を書き込むことができるかも知れません。特性値が書き込み可能である場合、値をNSDataのインスタンスとして表し、CBPeripheralのwriteValue:forCharacteristic:type:メソッドを次のように実行します。

NSLog(@"Writing value for characteristic %@", interestingCharacteristic);

[peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic

type:CBCharacteristicWriteWithResponse];

特性値を書き込む際には、その動作も指定できます。上の例ではCBCharacteristicWriteWithResponseを指定しているので、正常に書き込めたかどうか、ペリフェラルがアプリケーションに通知するようになります。指定可能な動作については、『CBPeripheralClassReference』の、CBCharacteristicWriteType列挙子に関する項を参照してください。

CBCharacteristicWriteWithResponseを指定した場合、ペリフェラルマネージャは書き込み後、デリゲートオブジェクトのperipheral:didWriteValueForCharacteristic:error:メソッドを呼び出します。書き込みに失敗したとき、その原因を出力するコード例を示します。

- (void)peripheral:(CBPeripheral *)peripheral

didWriteValueForCharacteristic:(CBCharacteristic *)characteristic

error:(NSError *)error {

セントラルが実行するタスク特性値を書き込む

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

21

Page 22: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

if (error) {

NSLog(@"Error writing characteristic value: %@",

[error localizedDescription]);

}

...

注意: ここで指定できる動作に制限があるかも知れません。どのような動作が指定できるかは、Characteristic Properties列挙子で定義されている所定のビットを参照することにより判断できます(詳しくは『CBCharacteristic Class Reference』を参照)。

セントラルが実行するタスク特性値を書き込む

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

22

Page 23: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

前章では、セントラル側の機器が実行する、主なBLEタスクについて説明しました。この章では、ペリフェラル側で実行する主なBLEタスクについて、Core Bluetoothフレームワークを使って実装する方法を説明します。ローカルデバイスにペリフェラルとしての役割を与えるアプリケーションを開発する際、以下に示すコード例が参考になるでしょう。具体的には次のようなタスクです。

● ペリフェラルマネージャオブジェクトを起動する

● ローカルのペリフェラルが提供するサービスや特性を設定する

● サービスや特性を当該デバイスのローカルデータベースに登録する

● サービスをアドバタイズする

● 接続されたセントラルからの読み書き要求に応答する

● 特性値が変化したとき、あらかじめ申し込まれていたセントラルに通知する

この章に示すコード例は簡略化してあり、そのまま実際のアプリケーションに組み込むことはできません。ペリフェラルとしての役割の実装に関するさらに進んだ話題(ヒント、技法、ベストプラクティス)を、章を改めて解説します。“Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)” (32 ページ)および“ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス” (48 ページ)を参照してください。

ペリフェラルマネージャを起動するローカルデバイスにペリフェラルとしての役割を実装するためには、まず、ペリフェラルマネージャ(CBPeripheralManagerオブジェクトで表す)のインスタンスを生成、初期化しなければなりません。これは次のようにして、CBPeripheralManagerクラスのinitWithDelegate:queue:options:

メソッドで行います。

myPeripheralManager =

[[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];

ここではselfを、ペリフェラルとしての役割に関係するイベントを受け取る、デリゲートオブジェクトとして設定しています。ディスパッチキューとしてnilを指定しているので、ペリフェラルマネージャはイベントのディスパッチ用に、メインキューを使います。

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

23

ペリフェラルが実行するタスク

Page 24: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

ペリフェラルマネージャは生成された後、デリゲートオブジェクトのperipheralManagerDidUpdateState:メソッドを呼び出します。このメソッドを、当該ペリフェラルでBLEが機能するように実装してください。実装方法について詳しくは、『CBPeripheralManagerDelegateProtocol Reference』を参照してください。

サービスおよび特性をセットアップする図 1-7 (14 ページ)に示したように、ローカル側ペリフェラルが提供するサービスや特性のデータベースは、木のような構成になります。このような木構成になるよう、実際にサービスや特性をセットアップしなければなりません。しかしその前に、サービスや特性をどのように識別するか、理解しておきましょう。

サービスや特性はUUIDで識別するペリフェラルのサービスや特性は、Bluetoothに特有の128ビットUUIDで識別します。Core BluetoothフレームワークではUUIDを、CBUUIDオブジェクトで表します。あらゆるサービスや特性を網羅してはいませんが、Bluetooth分科会(SIG、Special Interest Group)はよく使われるUUIDを多数、使いやすいよう16ビットに短縮して定義、公開しています。たとえば心拍サービスの16ビットUUIDは180Dとなっています。これは同等の128ビットUUIDである「0000180D-0000-1000-8000-00805F9B34FB」を短縮したもので、Bluetooth Base UUID(Bluetooth 4.0仕様のVolume 3、Part F、Section 3.2.1)が基盤となっています。

CBUUIDクラスには、アプリケーション開発において、長い形式のUUIDを簡便に扱うためのファクトリメソッドがあります。たとえば、心拍サービスの128ビットUUIDを文字列としてコード中に記述する代わりに、次のように、UUIDWithStringを用い、定義済みの16ビットUUIDからCBUUIDオブジェクトを生成できます。

CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString: @"180D"];

定義済みの16ビットUUIDからCBUUIDオブジェクトを生成する場合、Core Bluetoothは残りビットにBluetooth Base UUIDを充塡します。

独自のサービスや特性を識別するUUIDを生成する定義済みのBluetooth UUIDでは識別できないサービスや特性があるかも知れません。その場合、独自に128ビットUUIDを生成する必要があります。

ペリフェラルが実行するタスクサービスおよび特性をセットアップする

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

24

Page 25: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

128ビットUUIDは、コマンドラインユーティリティ「uuidgen」で簡単に生成できます。まず、「ターミナル(Terminal)」のウインドウを開いてください。次に、UUIDで識別するべきサービスや特性ごとに、「uuidgen」コマンドを実行して、次のように、128ビットの値を表すハイフン区切りのASCII文字列を得ます。

$ uuidgen

71DA3FD1-7E10-41C1-B16F-4430B506CDE7

このUUIDを引数としてUUIDWithStringメソッドを実行すれば、CBUUIDオブジェクトを生成できます。

CBUUID *myCustomServiceUUID =

[CBUUID UUIDWithString:@"71DA3FD1-7E10-41C1-B16F-4430B506CDE7"];

サービスおよび特性の木を構築するサービスや特性のUUID(CBUUIDオブジェクトで表す)が得られたので、可変のサービスや特性を表すオブジェクトを生成し、上述のような木構成にしていきます。たとえば次のように、特性のUUIDを引数としてCBMutableCharacteristicのinitWithType:properties:value:permissions:メソッドを実行することにより、可変の特性を生成できます。

myCharacteristic =

[[CBMutableCharacteristic alloc] initWithType:myCharacteristicUUID

properties:CBCharacteristicPropertyRead

value:myValue permissions:CBAttributePermissionsReadable];

次に、生成した可変の特性に対して、プロパティ、値、操作権限を設定します。プロパティや操作権限は、特性の値が読み取り/書き込み可能か、値の変化を通知するよう申し込むことができるか、などを表します。この例では、セントラルが接続して値を読み取れるよう設定しています。可変の特性に対して設定可能なプロパティや操作権限について詳しくは、『CBMutableCharacteristicClassReference』を参照してください。

ペリフェラルが実行するタスクサービスおよび特性をセットアップする

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

25

Page 26: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

注意: 特性の値を指定すると、この値はキャッシュの対象になり、読み取り可能であるようにプロパティや操作権限が設定されます。書き込みも可能にしたい、あるいは時間の経過に伴い変化するようにしたい場合は、値としてnilを指定しなければなりません。こうしておけば、セントラルから読み取り/書き込み要求を受け取ったペリフェラルマネージャが、値を動的に変更できるようになります。

可変の特性を生成したので、次にこれに関連づける可変のサービスを生成しましょう。これはCBMutableServiceクラスのinitWithType:primary:メソッドで行います。

myService = [[CBMutableService alloc] initWithType:myServiceUUID primary:YES];

この例では第2引数にYESを渡しているので、主サービスであることになります。主サービス(primaryservice)とは、デバイスの主たる機能のことです。他のサービスがこれを組み込む(参照する)ことも可能です。一方、副サービス(secondary service)とは、もっぱら他のサービスに組み込まれる(参照される)サービスのことです。たとえば、心拍モニタの主サービスは、心拍センサーから得た心拍データを公開することです。一方、センサーの電池の状態を知らせるのは副サービスです。

生成したサービスに特性を対応づけます。次のように、特性を表す配列を指定して行います。

myService.characteristics = @[myCharacteristic];

サービスや特性を登録するサービスと特性の木を構築できたので、次にこれを、デバイスのサービス/特性データベースに登録します。これもCore Bluetoothフレームワークを使えば簡単に実行できます。次のように、CBPeripheralManagerクラスのaddService:メソッドを実行してください。

[myPeripheralManager addService:myService];

このようにしてサービスを公開すると、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManager:didAddService:error:メソッドを呼び出します。エラーがあってサービスを公開できない場合、その原因を調べて対処するように実装してください。

- (void)peripheralManager:(CBPeripheralManager *)peripheral

didAddService:(CBService *)service

error:(NSError *)error {

ペリフェラルが実行するタスクサービスや特性を登録する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

26

Page 27: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

if (error) {

NSLog(@"Error publishing service: %@", [error localizedDescription]);

}

...

注意: サービスやこれに関連する特性をペリフェラルのデータベースに登録すると、当該サービスはキャッシュされ、変更はできなくなります。

サービスをアドバタイズするサービスや特性をデータベースに登録すれば、セントラルに向けてアドバタイズできるようになります。サービスのアドバタイズは次のように、CBPeripheralManagerクラスのstartAdvertising:メソッドで行います。その際、アドバタイズデータの辞書(NSDictionaryのインスタンス)を引数として渡します。

[myPeripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey :

@[myFirstService.UUID, mySecondService.UUID] }];

この例では、辞書のキーはCBAdvertisementDataServiceUUIDsKeyのみであり、その値は(アドバタイズするサービスのUUIDを表す)CBUUIDオブジェクトの配列(NSArrayのインスタンス)です。アドバタイズデータの辞書に指定しうるキーについては、『CBCentralManagerDelegate ProtocolReference』の「Advertisement Data Retrieval Keys」に記載されている定数を参照してください。もっとも、ペリフェラルマネージャオブジェクトに対して指定できるのは、CBAdvertisementDataLocalNameKeyとCBAdvertisementDataServiceUUIDsKeyの2つだけです。

ローカルのペリフェラルにあるデータのアドバタイズを始めると、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManagerDidStartAdvertising:error:メソッドを呼び出します。エラーがあってサービスをアドバタイズできない場合、その原因を調べて対処するように実装してください。

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral

error:(NSError *)error {

if (error) {

NSLog(@"Error advertising: %@", [error localizedDescription]);

ペリフェラルが実行するタスクサービスをアドバタイズする

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

27

Page 28: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

}

...

注意: データのアドバタイズは「ベストエフォート型」で行います。狭い空間内で、複数のアプリケーションが同時にアドバタイズすることもありうるからです。詳しくは『CBPeripheralManager Class Reference』の、startAdvertising:メソッドに関する項を参照してください。

アドバタイズの処理は、アプリケーションがバックグラウンド状態か否かによっても変わります。詳しくは次の章、“Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)” (32 ページ)を参照してください。

データのアドバタイズを始めると、リモートのセントラルが検出し、接続を試みるようになります。

セントラルからの読み書き要求に応答するリモートのセントラルと接続すると、読み取りや書き込みの要求が届くでしょう。これに適切に応答しなければなりません。以下の例はその手順を表しています。

接続したセントラルから、ある特性値の読み取り要求が届くと、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManager:didReceiveReadRequest:メソッドを呼び出します。デリゲートメソッドにはこの要求が、CBATTRequestオブジェクトの形で渡されます。このオブジェクトには、要求を満たすために使える、さまざまなプロパティがあります。

たとえば、ある特性値の単純な読み取り要求の場合、このCBATTRequestオブジェクトのプロパティを使って、デバイスのデータベースに登録されている特性が、読み取り要求の指定と合致しているかどうか確認できます。実装は、たとえば次のようになるでしょう。

- (void)peripheralManager:(CBPeripheralManager *)peripheral

didReceiveReadRequest:(CBATTRequest *)request {

if ([request.characteristic.UUID isEqual:myCharacteristic.UUID]) {

...

特性のUUIDが合致したら次に、読み取り要求されたインデックス位置が、該当する特性値の範囲外でないことを確認します。これは次のように、CBATTRequestオブジェクトのoffsetプロパティを使って行います。

ペリフェラルが実行するタスクセントラルからの読み書き要求に応答する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

28

Page 29: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

if (request.offset > myCharacteristic.value.length) {

[myPeripheralManager respondToRequest:request

withResult:CBATTErrorInvalidOffset];

return;

}

指定されたオフセットが適切であれば、このオブジェクトのvalueプロパティ(当初の値はnil)に、オフセットも考慮しながら、該当する特性の値を設定します。

request.value = [myCharacteristic.value

subdataWithRange:NSMakeRange(request.offset,

myCharacteristic.value.length - request.offset)];

その後、リモートのセントラルに対して、要求が満たされた旨応答します。これは、CBPeripheralManagerクラスのrespondToRequest:withResult:メソッドで、(valueプロパティを更新した)requestを返すことにより行います。

[myPeripheralManager respondToRequest:request withResult:CBATTErrorSuccess];

...

respondToRequest:withResult:メソッドは、peripheralManager:didReceiveReadRequest:デリゲートメソッドが呼び出される都度、1回ずつ実行します。

注意: 特性のUUIDが合致しなかった、あるいは何らかの理由で読み取りができなかった場合、要求を満たすことはできません。そのままrespondToRequest:withResult:メソッドで、原因を表す結果コードを返してください。指定できる結果コードの一覧が、『CoreBluetooth Constants Reference』の、CBATTError Constants列挙子の項にあります。

書き込み要求に対する応答も、特に難しいことはありません。接続したセントラルから、ある特性値の書き込み要求が届くと、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManager:didReceiveWriteRequests:メソッドを呼び出します。デリゲートメソッドにはこの要求が、1つ以上のCBATTRequestオブジェクトの配列として渡されます。それぞれが1件の書き込みを表します。書き込み要求に応じられることを確認した後、実際に書き込みを行います。

myCharacteristic.value = request.value;

ペリフェラルが実行するタスクセントラルからの読み書き要求に応答する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

29

Page 30: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

この例では省略していますが、特性値を書き込む際には、要求(request)のoffsetプロパティも考慮してください。

読み取り要求に対する応答と同様、respondToRequest:withResult:メソッドは、peripheralManager:didReceiveWriteRequests:デリゲートメソッドが呼び出される都度、1回ずつ実行します。なお、このrespondToRequest:withResult:デリゲートメソッドには配列の形で複数のCBATTRequestオブジェクトが渡されますが、peripheralManager:didReceiveWriteRequests:

メソッドの第1引数に指定するのは単一のオブジェクトです。次のように、request配列の先頭要素を渡してください。

[myPeripheralManager respondToRequest:[requests objectAtIndex:0]

withResult:CBATTErrorSuccess];

注意: 複数件の要求がある場合、一括して扱います。いずれかの要求に応じることができなければ、ほかの要求にも応じるべきではありません。そのままrespondToRequest:withResult:メソッドで、原因を表す結果コードを返してください。

特性値が変化したとき、あらかじめ申し込まれているセントラルに通知するセントラルは、特性を指定して、値が変化したら通知するよう申し込むことができます(“特性の値が変化したときに通知するよう申し込む” (20 ページ)を参照)。この場合、該当する特性値が変化したら通知を送らなければなりません。その方法を以下に示します。

セントラルが特性値の変化を通知するよう申し込むと、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManager:central:didSubscribeToCharacteristic:メソッドを呼び出します。

- (void)peripheralManager:(CBPeripheralManager *)peripheral

central:(CBCentral *)central

didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {

NSLog(@"Central subscribed to characteristic %@", characteristic);

...

これ以降、値が変化したらセントラルに通知することになります。

ペリフェラルが実行するタスク特性値が変化したとき、あらかじめ申し込まれているセントラルに通知する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

30

Page 31: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

次に、新しい特性値を取得し、セントラルに通知します。これはCBPeripheralManagerクラスのupdateValue:forCharacteristic:onSubscribedCentrals:メソッドで行います。

NSData *updatedValue = // 新しい特性値を取得

BOOL didSendValue = [myPeripheralManager updateValue:updatedValue

forCharacteristic:characteristic onSubscribedCentrals:nil];

このとき、最後の引数で、送信先のセントラルを指定できます。例のようにnilを指定した場合は、申し込みを受け付けたセントラルすべてが対象になります(申し込みしていない機器は対象外)。

updateValue:forCharacteristic:onSubscribedCentrals:メソッドは、新しい特性値の送信に成功したかどうかを表すブール値を返します。送信処理のため内部的に使っているキューがいっぱいになった場合、戻り値はNOになります。その後、キューに余裕が生じて送信できるようになると、ペリフェラルマネージャは、デリゲートオブジェクトのperipheralManagerIsReadyToUpdateSubscribers:メソッドを呼び出します。再びupdateValue:forCharacteristic:onSubscribedCentrals:メソッドを使って、値を再送するように実装するとよいでしょう。

注意: 新しい特性値は、1パケット内に収容し、通知としてセントラルに送信します。新しい特性値の全体を、(updateValue:forCharacteristic:onSubscribedCentrals:メソッドを1回だけ呼び出して、)1件の通知で返すのです。

しかし特性値の長さによっては、通知パケットに収容できず、全体を送信できないかも知れません。その場合は、セントラル側がCBPeripheralクラスのreadValueForCharacteristic:

メソッドを呼び出して、値全体を取得するように実装してください。

ペリフェラルが実行するタスク特性値が変化したとき、あらかじめ申し込まれているセントラルに通知する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

31

Page 32: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

iOSアプリケーションでは、フォアグラウンド/バックグラウンドのどちらで動作しているかを認識することが重要です。iOSデバイスはリソースの制約が厳しいので、バックグラウンド状態になったら、フォアグラウンドのときとは動作を変える必要があるからです。iOSにおけるマルチタスクの概要については、『iOS App Programming Guide』の“App States and Multitasking”を参照してください。

バックグラウンド状態や一時停止状態のとき、デフォルトでは、Core Bluetoothに組み込まれた主なタスク(セントラル側、ペリフェラル側とも)が動作しなくなります。とはいえ、Core Bluetoothのバックグラウンド実行モードに対応する旨を宣言しておけば、一時停止状態から起き上がり(ウェイクアップ)、イベントを処理できるようになります。もちろん、あらゆるタスクをバックグラウンドでも動くようにする必要はありませんが、重要なイベントが発生したとき、起こしてもらうようシステムに申し込んでおくことは可能なのです。

Core Bluetoothのバックグラウンド実行モード(セントラル側、ペリフェラル側の一方または両方)に対応したアプリケーションであっても、無制限に動作を続けることはできません。システムがいつでも強制的に停止する可能性があります。メモリを解放し、フォアグラウンドアプリケーションに割り当るためで、そうなると、たとえば動作中/保留中の接続も失われてしまいます。iOS 7以降、セントラル/ペリフェラルマネージャオブジェクトの状態を保存しておき、次のアプリケーション起動時に復元できるようになりました。この機能を活用すれば、長時間にわたるアクションも実装できます。

フォアグラウンド動作のみのアプリケーション多くのiOSアプリケーションと同様、バックグラウンドタスクの実行許可を要求していない限り、バックグラウンド状態になるとすぐに一時停止状態に移行します。この状態ではBluetooth関係のタスクを実行できませんし、フォアグラウンド状態に戻るまでは、Bluetooth関係のイベントを認識することもありません。

セントラルの側について言うと、フォアグラウンド動作のみのアプリケーション(Core Bluetoothのバックグラウンド実行モードを宣言していないもの)は、バックグラウンド状態や一時停止状態の間、アドバタイズしているペリフェラルを走査し、検出することができません。また、ペリフェラルの側も、アドバタイズを出さなくなります。また、あるサービスの特性値をセントラルが取得しようとしても、エラーになってしまいます。

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

32

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)

Page 33: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

このようなデフォルトの動作は、用途にもよりますが、アプリケーションにさまざまな影響を及ぼします。たとえば、接続先のペリフェラルと、データをやり取りしているとしましょう。その最中に、(たとえばユーザが別のアプリケーションに切り替えたため、)一時停止状態に移行したとします。その間に接続が切れたとしても、フォアグラウンド状態に戻るまでアプリケーションは認識できません。

ペリフェラル接続オプションを活用するフォアグラウンド動作のみのアプリケーションが一時停止状態の間に、Bluetooth関係のイベントが発生した場合、システムがすべてキューに登録しておき、フォアグラウンド状態に戻ってから配送するようになっています。もっとも、いくつかのイベントについては、一時停止状態であってもユーザに警告する手段があります。ユーザはこの警告に応じて、フォアグラウンド状態に戻すかどうか判断できるのです。

この仕組みを有効にするためには、CBCentralManagerクラスのconnectPeripheral:options:メソッドで接続する際に、次のいずれかのペリフェラル接続オプションを指定してください。

● CBConnectPeripheralOptionNotifyOnConnectionKey - 当該機器との接続に成功したとき、アプリケーションが一時停止状態であれば、その旨の警告を表示するようになります。

● CBConnectPeripheralOptionNotifyOnDisconnectionKey - 当該機器との接続が切れたとき、アプリケーションが一時停止状態であれば、その旨の警告を表示するようになります。

● CBConnectPeripheralOptionNotifyOnNotificationKey - 当該機器から特性値が変化した旨の通知が届いたとき、アプリケーションが一時停止状態であれば、その旨の警告を表示するようになります。

ペリフェラル接続オプションについて詳しくは、『CBCentralManagerClassReference』の、「Peripheral

Connection Options」定数に関する項を参照してください。

Core Bluetoothのバックグラウンド実行モードバックグラウンド状態でもBluetooth関係のタスクを実行できるようにしたい場合は、Core Bluetoothのバックグラウンド実行モードに対応する旨、情報プロパティリストファイル(Info.plist)に宣言しなければなりません。この宣言があれば、Bluetooth関係のイベントが発生するとシステムが当該アプリケーションを起こす(ウェイクアップ)ようになるので、当該イベントを処理できるのです。心拍モニタのように、定期的にBLEデバイスからデータが送られてくる場合、これが重要な働きをします。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)Core Bluetoothのバックグラウンド実行モード

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

33

Page 34: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

アプリケーションが宣言できるCore Bluetoothのバックグラウンド実行モードは、セントラルとしての役割を実装しているか、ペリフェラルとしての役割を実装しているか、に応じて2種類あります。両方の役割を実装したアプリケーションであれば、両方を宣言しても構いません。実際の宣言は、UIBackgroundModesキーをInfo.plistファイルに追加し、値として、次のいずれかの文字列を収容した配列を与えることにより行います。

● bluetooth-central - アプリケーションはCore Bluetoothフレームワークを使って、BLEペリフェラルと通信します。

● bluetooth-peripheral - アプリケーションはCore Bluetoothフレームワークを使って、データを他の機器に公開します。

注意: Xcodeのプロパティリストエディタは通常、多くのキーについて、実際のキー名ではなく、人が読める形の文字列を表示します。Info.plistファイルに現れる実際のキー名を表示したい場合は、エディタウインドウ上でControlキーを押しながらキー名をクリックし、「Show Raw Keys/Values」をオンにしてください。

Info.plistファイルの設定(記述)方法について詳しくは、『Property List Editor Help』を参照してください。

バックグラウンド実行モード「bluetooth-central」セントラルとしての役割を実装したアプリケーションが、Info.plistファイルにUIBackgroundModes

キーを宣言し、bluetooth-centralという値を与えている場合、バックグラウンドでもBluetooth関係のタスクを実行できます。バックグラウンド状態でも、ペリフェラルを検出、接続し、データを調査し、やり取りすることができるのです。さらに、CBCentralManagerDelegateやCBPeripheralDelegateのデリゲートメソッドが呼び出されれば、システムは当該アプリケーションを起こします(ウェイクアップ)。したがって、接続が確立した、切断された、変更された特性値を受け取った、セントラルマネージャの状態が変化したなど、中心機器としての役割にかかわる重要なイベントを処理できることになります。

バックグラウンド状態でもBluetooth関係の多くのタスクを実行できますが、ペリフェラルを走査する動作は、フォアグラウンド状態のときとは若干異なるので注意してください。具体的には次のような違いがあります。

● 走査オプションキーCBCentralManagerScanOptionAllowDuplicatesKeyは無視されます。また、アドバタイズしているペリフェラルを繰り返し検出しても、1回の検出イベントにまとめられます。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)Core Bluetoothのバックグラウンド実行モード

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

34

Page 35: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

● ペリフェラルを走査しているアプリケーションがすべてバックグラウンド状態であれば、アドバタイズパケットを走査する間隔が長くなります。したがって、検出に時間がかかるかも知れません。

以上のような動作の違いは、電波の送出を減らし、電池の寿命を延ばすのが目的です。

バックグラウンド実行モード「bluetooth-peripheral」バックグラウンド状態でもペリフェラルとしてのタスクを実行するためには、Info.plistファイルにUIBackgroundModesキーを宣言し、bluetooth-peripheralという値を与える必要があります。この記述がInfo.plistファイルにあれば、読み取り、書き込み、特性値が変化したときの通知ができるよう、必要に応じてシステムがアプリケーションを起こします(ウェイクアップ)。

さらに、バックグラウンド状態でもアドバタイズを送出できるようになります。ただし、アドバタイズを送出する動作は、フォアグラウンド状態のときとは若干異なるので注意してください。具体的には次のような違いがあります。

● アドバタイズオプションキーCBAdvertisementDataLocalNameKeyは無視されます。また、ペリフェラルのローカル名はアドバタイズされません。

● アドバタイズキーCBAdvertisementDataServiceUUIDsKeyの値として記述されているサービスUUIDは、特別な「オーバーフロー」領域に入るため、明示的にこのUUIDを指定して走査しない限り、検出できないようになります。

● アドバタイズを送出するアプリケーションがすべてバックグラウンド状態であれば、送出頻度が落ちるかも知れません。

バックグラウンド実行モードを適切に活かすアプリケーションの用途によっては、バックグラウンド実行モードの宣言が必須になりますが、その場合でも実行には責任が伴います。Bluetooth関係のタスクの多くは、iOSデバイスの無線機能を積極的に使うので、電池の寿命に大きく影響します。バックグラウンドでの処理は控えめにしてください。Bluetooth関係のイベントに応じて「起こされた」アプリケーションは、できるだけ短時間でイベントを処理し、再び停止状態に戻らなければなりません。

Core Bluetoothのバックグラウンド実行モードを宣言する場合、以下のガイドラインに従ってアプリケーションを実装してください。

● セッションベースで実装し、Bluetooth関係のイベントの配送をいつ開始/停止するか、ユーザが制御するためのインターフェイスを設けてください。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)バックグラウンド実行モードを適切に活かす

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

35

Page 36: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

● 「起こされて」から約10秒以内に、タスクを終了する必要があります。できるだけ短時間で処理し、一時停止状態に戻るようにしなければなりません。バックグラウンドでの実行に時間がかかりすぎているアプリケーションは、システムによって抑制されるか、強制終了させられる可能性があります。

● システムが当該アプリケーションを起こす原因となった事象と無関係なタスクを、ついでに実行するのは避けてください。

バックグラウンド状態のアプリケーションの動作に関するより一般的な情報が、『iOSAppProgrammingGuide』の“Being a Responsible Background App” in iOS App Programming Guideに載っています。

長時間にわたるアクションをバックグラウンドで実行するアプリケーションによっては、Core Bluetoothフレームワークを利用して、長時間にわたるアクションをバックグラウンドで実行することがあります。たとえばiOSデバイス用のホームセキュリティアプリケーションを考えてみましょう。これはBluetooth技術を搭載した施錠システムと通信します。アプリケーションと施錠システムが連携して、ユーザが家を出れば自動的に鍵をかけ、帰ってくれば鍵を開けます。いずれもバックグラウンド状態での動作です。ユーザが家から離れると、iOSデバイスは施錠システムと通信できる範囲外になるため、接続が失われることがあります。するとアプリケーションは、CBCentralManagerクラスのconnectPeripheral:options:メソッドを実行します。接続要求はタイムアウトにならないので、家に帰れば再接続されることになります。

ユーザが数日にわたって家を離れたとしましょう。その間にシステムがアプリケーションを停止したとすれば、家に帰り着いたとき施錠システムに再接続することができず、ユーザは閉め出されてしまうかも知れません。このようなアプリケーションは、Core Bluetoothを使って、長時間にわたり、接続を監視するなどのアクションを実行し続けなければならないのです。

状態の保存と復元Core Bluetoothには状態の保存/復元機能が組み込まれています。アプリケーションはこれを利用して、セントラル/ペリフェラルマネージャの状態を保存し、アプリケーション自身が停止していても、代わりにBluetooth関係のタスクを実行するよう、システムに要求することができます。タスクが完了すると、システムはアプリケーションを起動し直してバックグラウンド状態にします。したがってアプリケーションは、状態を復元し、イベントを適切に処理できることになります。上述のホームセキュリティアプリケーションの場合、システムは接続要求を監視し、ユーザが帰宅して接続要求の処理が完了した時点でアプリケーションを再度立ち上げます。したがってアプリケーションは、コールバックとして、デリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを処理できることになります。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

36

Page 37: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothは、セントラル/ペリフェラルとしての役割を実装したアプリケーションに代わって、状態の保存と復元を行います。アプリケーションにセントラルとしての役割を実装し、状態の保存/復元機能を組み込んだ場合、システムは、アプリケーションを停止してメモリを解放する際、セントラルマネージャオブジェクトの状態を保存します(セントラルマネージャが複数ある場合、どれをシステムに管理させるか選択可能)。具体的には、指定されたCBCentralManagerオブジェクトについて、次の事項を管理するようになっています。

● セントラルマネージャが走査するサービス(および走査開始時に指定されたオプション)

● セントラルマネージャが接続を試み、あるいは既に接続しているペリフェラル

● セントラルマネージャが変更の通知を申し込んでいる特性

ペリフェラルとしての役割を実装したアプリケーションも、同様にこの機能を活用できます。システムはCBPeripheralManagerオブジェクトについて、次の事項を管理します。

● ペリフェラルマネージャがアドバタイズしたデータ

● ペリフェラルマネージャがデバイスのデータベースに登録したサービスと特性

● 特性値の変化を通知するよう申し込んでいるセントラル

(走査していたペリフェラルを検出したなどのため、)システムがアプリケーションを立ち上げ直し、バックグラウンド状態に移行させると、アプリケーションはセントラル/ペリフェラルマネージャのインスタンスを改めて生成し、その状態を復元できます。以下の節では、状態の保存/復元機能をアプリケーションに組み込む方法を、詳しく説明します。

状態の保存/復元機能を組み込むCore Bluetoothの状態保存/復元はオプトイン機能であって、これを活かすためにはアプリケーション側の関与が必要です。その手順を以下に示します。

1. (必須)セントラル/ペリフェラルマネージャを生成/初期化する際に、状態の保存/復元機能をオプトインします。詳しくは“状態の保存/復元機能をオプトインする”を参照してください。

2. (必須)システムがアプリケーションを立ち上げ直したときに、セントラル/ペリフェラルマネージャを初期化し直すよう実装します。詳しくは“セントラル/ペリフェラルマネージャを再初期化する” (38 ページ)を参照してください。

3. (必須)適切に復元を行うデリゲートメソッドを実装します。詳しくは“復元を行う適切なデリゲートメソッドを実装する” (39 ページ)を参照してください。

4. (必要に応じて)セントラル/ペリフェラルマネージャの初期化プロセスを実装し直します。詳しくは“初期化プロセスを実装し直す” (40 ページ)を参照してください。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

37

Page 38: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

状態の保存/復元機能をオプトインする状態の保存/復元機能をオプトインするためには、セントラル/ペリフェラルマネージャを生成、初期化する際に、一意的な復元識別子を指定します。復元識別子(restoration identifier)は、Core Bluetoothやアプリケーション自身が、セントラル/ペリフェラルマネージャを識別するために使う文字列です。その中身はアプリケーション側で自由に決めて構いませんが、この文字列が存在すれば、Core Bluetoothは当該オブジェクトの状態を保存する必要があると認識します。逆に言えば、Core Bluetoothが状態を保存するのは、復元識別子を指定したものに限るということです。

たとえば、CBCentralManagerのインスタンスのみを使ってセントラルとしての役割を実装するアプリケーションの場合、これを生成、初期化する際に、初期化オプションとしてCBCentralManagerOptionRestoreIdentifierKeyを与え、セントラルマネージャの復元識別子を指定してください。

myCentralManager =

[[CBCentralManager alloc] initWithDelegate:self queue:nil

options:@{ CBCentralManagerOptionRestoreIdentifierKey:

@"myCentralManagerIdentifier" }];

この例には示していませんが、ペリフェラルマネージャオブジェクトを使うアプリケーションの場合も同様です。初期化オプションとしてCBPeripheralManagerOptionRestoreIdentifierKeyを与え、ペリフェラルマネージャの復元識別子を指定します。

注意: CBCentralManagerやCBPeripheralManagerのインスタンスが複数ある場合、それぞれに一意的な復元識別子を与えて、システムが識別できるようにしてください。

セントラル/ペリフェラルマネージャを再初期化するシステムがアプリケーションを立ち上げ直してバックグラウンド状態にしたとき、まず必要なのは、セントラル/ペリフェラルマネージャを初期化し直すことです。このとき、当初生成したときと同じ復元識別子を渡します。セントラル/ペリフェラルマネージャがひとつだけで、アプリケーションが動作する限り常に活きているならば、ほかに必要な処理はありません。

一方、アプリケーションに複数のセントラル/ペリフェラルマネージャがある、あるいは動作中、常に活きているわけではない場合、どのマネージャを生成し直すか、きちんと管理する必要があります。アプリケーションが停止する際、システムはマネージャオブジェクトの復元識別子を保存しますが、そのリストを取得できます。アプリケーションデリゲートのapplication:didFinishLaunchingWithOptions:メソッドを実装し、引数として渡された起動オプションから、キーUIApplicationLaunchOptionsBluetoothCentralsKeyまたはUIApplicationLaunchOptionsBluetoothPeripheralsKeyを指定してアクセスしてください。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

38

Page 39: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

たとえばセントラルマネージャオブジェクトの復元識別子は、次のようなコードで取得できます。

- (BOOL)application:(UIApplication *)application

didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

NSArray *centralManagerIdentifiers =

launchOptions[UIApplicationLaunchOptionsBluetoothCentralsKey];

...

取得したリストの中からどれが該当するか調べ、適切なセントラルマネージャオブジェクトを再生成してください。

注意: このときシステムがデリゲートメソッドに渡すのは、停止中に何らかのタスクを実行したセントラル/ペリフェラルマネージャの復元識別子だけです。起動オプションのキーについて詳しくは、『UIApplicationDelegate Protocol Reference』を参照してください。

復元を行う適切なデリゲートメソッドを実装する該当するセントラル/ペリフェラルマネージャを再生成した後、Bluetoothシステムの状態に同期させる、という方法で状態を復元します。(アプリケーションが停止中に)システムが代わって実行した後の状態を再現するため、復元処理用の適切なデリゲートメソッドを実装しなければなりません。具体的には、セントラルマネージャであればcentralManager:willRestoreState:、ペリフェラルマネージャであればperipheralManager:willRestoreState:です。

重要: Core Bluetoothの状態保存/復元機能をオプトインしたアプリケーションの場合、アプリケーションが再起動され、バックグラウンド状態に移行して最初に呼び出されるメソッド(centralManager:willRestoreState:またはperipheralManager:willRestoreState:)が、Bluetooth関係のタスクをすべて行います。状態保存機能をオプトインしていない(あるいは起動時に復元するべきものがない)場合、最初に呼び出されるデリゲートメソッドは、centralManagerDidUpdateState:またはperipheralManagerDidUpdateState:です。

どちらのデリゲートメソッドも、最後の引数として、アプリケーション停止時に保持していたマネージャに関する情報を収容した辞書が渡されます。辞書に現れうるキーの一覧が、『CBCentralManagerDelegate Protocol Reference』のCentral Manager State Restoration Options

定数、『CBPeripheralManagerDelegate Protocol Reference』のPeripheral_Manager_State_Restoration_Options定数の項にそれぞれ載っています。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

39

Page 40: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

CBCentralManagerオブジェクトの状態を復元するには、centralManager:willRestoreState:デリゲートメソッドに渡される辞書に、所定のキーを指定します。たとえば、アプリケーションが停止する時点で、セントラルマネージャに接続中または保留中の接続があった場合、システムが変わって監視を続けます。次のように、CBCentralManagerRestoredStatePeripheralsKeyという辞書キーを指定することにより、セントラルマネージャが接続し、または接続を試みていたペリフェラル(CBPeripheralオブジェクトで表す)のリストを取得できます。

- (void)centralManager:(CBCentralManager *)central

willRestoreState:(NSDictionary *)state {

NSArray *peripherals =

state[CBCentralManagerRestoredStatePeripheralsKey];

...

この例で、復元したペリフェラルのリストを使って実行するべき処理は、用途に応じて決まります。たとえば、セントラルマネージャが検出したペリフェラルのリストを保持していた場合、復元されたペリフェラルをこのリストに追加し、併せて参照できるようにするかも知れません。“検出したペリフェラルに接続する” (17 ページ)で説明したように、適切なコールバックが呼び出されるよう、ペリフェラルのデリゲートを設定してください。

CBPeripheralManagerオブジェクトの状態を復元する場合も同様に、peripheralManager:willRestoreState:デリゲートメソッドに渡される辞書に、所定のキーを指定します。

初期化プロセスを実装し直すここまでの手順(必須)を実装した後、セントラル/ペリフェラルマネージャの初期化プロセスを実装し直す必要がないか検討してください。これは必須ではありませんが、アプリケーションの円滑な動作には重要かも知れません。たとえば、アプリケーションが停止した時点で、接続先ペリフェラルがどのようなデータを提供するか、調査している最中だったとしましょう。このペリフェラルの状態を復元したとき、停止時点までにサービスをどこまで検出していたかは分かりません。しかし、(最初から検出し直すのではなく、)その時点の状態から続行できる方が望ましいでしょう。

たとえば、デリゲートのcentralManagerDidUpdateState:メソッドでアプリケーションの初期化を行う際、復元したペリフェラルについて、(停止時点までに)あるサービスが検出済みであったかどうか、次のようにして調べることができます。

NSUInteger serviceUUIDIndex =

[peripheral.services indexOfObjectPassingTest:^BOOL(CBService *obj,

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

40

Page 41: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

NSUInteger index, BOOL *stop) {

return [obj.UUID isEqual:myServiceUUIDString];

}];

if (serviceUUIDIndex == NSNotFound) {

[peripheral discoverServices:@[myServiceUUIDString]];

...

このように、サービスを検出している最中にアプリケーションが停止した場合、まずはその時点までに取得できたデータを、discoverServices:メソッドで調査することから始めます。サービスが検出済みであった場合は次に、必要な特性が検出済みかどうか(さらに、特性値の変化を通知するよう申し込み済みかどうか)を確認するとよいでしょう。このように初期化プロセスを実装し直すことにより、状況に応じて適切なメソッドを呼び出せるようになります。

Core Bluetoothのバックグラウンド処理(iOSアプリケーション用)長時間にわたるアクションをバックグラウンドで実行する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

41

Page 42: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothフレームワークを導入すれば、アプリケーションはセントラル側のさまざまなトランザクションを、容易に実装できるようになります。とは言え、ペリフェラルの検出や接続、リモートのペリフェラルが持つデータの調査や読み書きなど、セントラルとしてのさまざまなタスクを、的確に制御できるようにしなければなりません。この章では、特にiOSデバイス用アプリケーションについて、的確な制御のために考慮するべきガイドラインやベストプラクティスを紹介します。

電波の使い方や電池の寿命に注意を払うBLE機器とやり取りするアプリケーションを開発する際には、通信のために電波信号を送出していることを意識してください。ほかの種類の無線通信(Wi-Fi、旧式のBluetooth、同じBLEを使う他のアプリケーションなど)が、同じ周波数帯域を使っているかも知れないので、電波の送出は必要最小限にしなければなりません。

これはiOSデバイス用アプリケーションの場合特に重要です。電池の寿命にも大きく影響するからです。節度を持って電波を利用するためにも、以下のガイドラインに従ってください。結果的に、アプリケーションの性能が向上し、電池の寿命を延ばすことにも役立つでしょう。

デバイスの走査は必要な場合にのみ行うセントラルは、CBCentralManagerクラスのscanForPeripheralsWithServices:options:メソッドで、サービスをアドバタイズしているリモートのペリフェラルを検出するわけですが、これは明示的に停止されるまで続きます。

接続先が見つかり、さらに検出する必要がないのであれば、走査を停止してください。これはCBCentralManagerクラスのstopScanメソッドで行います(“検出したペリフェラルに接続する” (17 ページ)を参照)。

必要がなければCBCentralManagerScanOptionAllowDuplicatesKeyオプションを指定しないリモートのペリフェラルは、1秒間に複数のアドバタイズパケットを送出して、自身の存在を知らしめようとすることがあります。デバイスを走査するscanForPeripheralsWithServices:options:

メソッドは通常、ペリフェラルを繰り返し検出しても、1件の検出イベントにまとめてしまいます。すなわち、セントラルマネージャはデリゲートオブジェクトの

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

42

リモートのペリフェラルとのやり取りに関するベストプラクティス

Page 43: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

centralManager:didDiscoverPeripheral:advertisementData:RSSI:メソッドを、届いたアドバタイズパケットの数にかかわらず、新たにペリフェラルを検出するごとに1回だけ呼び出します。また、検出済みのペリフェラルであっても、アドバタイズの内容が変化した場合にはこのデリゲートメソッドを呼び出します。

scanForPeripheralsWithServices:options:メソッドに、走査オプションとしてCBCentralManagerScanOptionAllowDuplicatesKey定数を指定することにより、この動作を変更できます。ペリフェラルからアドバタイズパケットが届く都度、検出イベントが生成されるようになるのです。状況によってはこれが有用です。ペリフェラルまでの距離(受信信号強度、RSSI(ReceivedSignal Strength Indicator))に基づいて、接続するか否かを判断するような場合です。しかしながら、電池の寿命やアプリケーション性能に悪影響があるかも知れません。本当に必要な状況でのみ指定するようにしてください。

ペリフェラルのデータを的確に調査するアプリケーションにとって当面関心のないサービスや特性も、ペリフェラルは提供しているかも知れません。サービスや特性をすべて検出しようとすると、電池の寿命や処理性能に悪影響があります。本当に必要なサービスや特性のみ検出するようにしてください。

たとえば、多くのサービスを提供するペリフェラルに接続しているけれども、アプリケーションが実際に必要とするのは2つだけであるとしましょう。この場合、該当する2つだけを検出することができます。次のように、サービスのUUID(CBUUIDオブジェクトで表される)の配列を、CBPeripheralクラスのdiscoverServices:メソッドに渡してください。

[peripheral discoverServices:@[firstServiceUUID, secondServiceUUID]];

関心のある2つのサービスを検出した後、同様にして、関心がある特性のみを検出できます。(サービスごとに)該当する特性を表すUUIDの配列を、CBPeripheralクラスのdiscoverCharacteristics:forService:メソッドに渡してください。

頻繁に変化する特性については、値の変化を通知するよう申し込む“特性の値を取得する” (19 ページ)で説明したように、特性値を取得する方法は2つあります。

● 明示的にポーリングして特性値を取得する方法。必要の都度、readValueForCharacteristic:

メソッドを呼び出します。

● 特性値が変化する都度、通知を送るよう申し込む方法。1回だけsetNotifyValue:forCharacteristic:メソッドを実行します。

特に特性値が頻繁に変化する場合、できるだけ後者の方法を使うとよいでしょう。具体的な手順については“特性の値が変化したときに通知するよう申し込む” (20 ページ)を参照してください。

リモートのペリフェラルとのやり取りに関するベストプラクティス電波の使い方や電池の寿命に注意を払う

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

43

Page 44: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

必要なデータがすべて得られたら切断する接続の必要がなくなり次第すぐに切断すれば、電波の使用を抑制できます。次のような場合には切断してください。

● 通知を申し込んでいるどの特性についても、通知が届かなくなったとき(通知が届いているか否かは、当該特性のisNotifyingプロパティで確認可)。

● 必要なデータがすべて揃ったとき。

いずれの場合も、通知の申し込みを取り消してから切断してください。取り消しは、第1引数をNOとしてsetNotifyValue:forCharacteristic:メソッドを呼び出すことにより行います。ペリフェラルとの接続切断は、次のように、CBCentralManagerクラスのcancelPeripheralConnection:メソッドで行います。

[myCentralManager cancelPeripheralConnection:peripheral];

注意: cancelPeripheralConnection:メソッドは非ブロック型であり、CBPeripheralクラスのコマンド(切断しようとしているペリフェラルに対するもの)で保留状態のものは、実行を停止するかどうか分かりません。他のアプリケーションがまだ接続しているかも知れないので、ローカル接続を取り消しても、物理リンクが即座に切断されるとは限りません。しかし当該アプリケーションに関する限り、切断されたと看做してよい状態になるので、セントラルマネージャは、デリゲートオブジェクトのcentralManager:didDisconnectPeripheral:error:メソッドを呼び出します。

ペリフェラルに再接続するCore Bluetoothフレームワークには、ペリフェラルに再接続する方法が、次のように3つあります。

● 既知のペリフェラル(これまでに検出または接続したもの)のリストをretrievePeripheralsWithIdentifiers:メソッドで取得し、該当するペリフェラルがこの中にあれば接続を試みる方法。詳しくは“既知のペリフェラルのリストを取得する” (46 ページ)で説明します。

● システムに接続されているペリフェラルのリストをretrieveConnectedPeripheralsWithServices:メソッドで取得し、該当するペリフェラルがこの中にあれば、アプリケーションに(ローカルに)接続する方法。詳しくは“接続済みペリフェラルのリストを取得する” (47 ページ)で説明します。

リモートのペリフェラルとのやり取りに関するベストプラクティスペリフェラルに再接続する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

44

Page 45: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

● scanForPeripheralsWithServices:options:メソッドで走査してペリフェラルを検出し、見つかったら接続する方法。詳しくは“アドバタイズしているペリフェラルを検出する” (16 ページ)および“検出したペリフェラルに接続する” (17 ページ)を参照してください。

用途にもよりますが、再接続の都度、同じペリフェラルを走査、検出するのは、あまり望ましくないでしょう。まずは別の方法で再接続を試みてください。図 5-1のように、上述の順に試すというのもひとつの方法です。

図 5-1 再接続処理の流れの例

リモートのペリフェラルとのやり取りに関するベストプラクティスペリフェラルに再接続する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

45

Page 46: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

注意: アプリケーションの用途によって、試みるべき方法とその順序は違うかも知れません。第1の方法はまったく試みない、第1と第2の方法を並行して試みる、などの流れも考えられます。

既知のペリフェラルのリストを取得するシステムは初めて検出したペリフェラルに対して、識別子(NSUUIDオブジェクトで表されるUUID)を生成します。この識別子を(たとえばNSUserDefaultsクラスのリソースを使って)保存しておけば、後でこれを使って、CBCentralManagerクラスのretrievePeripheralsWithIdentifiers:メソッドで再接続できます。以下、このメソッドを使って、一度接続したことがあるペリフェラルに再接続する方法を示します。

アプリケーションの起動時に、これまでに検出、接続し(、その識別子を保存しておい)たペリフェラルの識別子をまとめた配列を渡して、次のようにretrievePeripheralsWithIdentifiers:メソッドを実行します。

knownPeripherals =

[myCentralManager retrievePeripheralsWithIdentifiers:savedIdentifiers];

セントラルマネージャは、指定された識別子を、過去に検出したペリフェラルの識別子と照合し、その結果をCBPeripheralオブジェクトの配列として返します。ひとつも合致しなければ配列は空なので、ほかの方法を試みることになります。そうでなければ、(適当なUIを設けて)再接続先をユーザが選択できるようにしてください。

ユーザがペリフェラルを選択したら、CBCentralManagerクラスのconnectPeripheral:options:メソッドで接続を試みます。接続が可能であれば、セントラルマネージャはデリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを呼び出します。この時点でペリフェラルは、再接続された状態になっています。

リモートのペリフェラルとのやり取りに関するベストプラクティスペリフェラルに再接続する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

46

Page 47: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

注意: 何らかの理由で、ペリフェラルに接続できないこともあります。たとえば、セントラルから離れたところに移動してしまっているかも知れません。さらに、BLE機器によっては、アドレスが定期的に、ランダムに変わります。すぐ近くにあったとしても、システムが検出した時点以降にアドレスが変わっていれば、接続しようとしているCBPeripheralオブジェクトと実際のペリフェラルが対応しないことになります。これが原因で再接続できなかった場合、改めてscanForPeripheralsWithServices:options:メソッドで検出しなければなりません。

ランダムに変わるアドレスについて詳しくは、Bluetooth 4.0仕様のVolume 3、Part C、Section10.8および「Bluetooth Accessory Design Guidelines for Apple Products」を参照してください。

接続済みペリフェラルのリストを取得するペリフェラルに再接続するもうひとつの方法として、当該ペリフェラルが(たとえば他のアプリケーションによって)システムに接続済みでないか調べる、というものがあります。これはCBCentralManagerクラスのretrieveConnectedPeripheralsWithServices:メソッドで行います。戻り値は、接続済みペリフェラルを表すCBPeripheralオブジェクトの配列です。

複数のペリフェラルが接続されているかも知れないので、(サービスのUUIDを表す)CBUUIDオブジェクトの配列を引数として渡します。システムに接続済みで、かつ、指定したサービスを提供するペリフェラルのみ取得できます。該当するペリフェラルがなければ配列は空なので、ほかの方法を試みることになります。そうでなければ、(適当なUIを設けて)再接続先をユーザが選択できるようにしてください。

ユーザがペリフェラルを選択したら、CBCentralManagerクラスのconnectPeripheral:options:メソッドで、当該アプリケーションにローカルに接続します(システムには接続済みでも、アプリケーションと接続しなければデータのやり取りはできません)。ローカルな接続が確立すると、セントラルマネージャはデリゲートオブジェクトのcentralManager:didConnectPeripheral:メソッドを呼び出します。この時点でペリフェラルは、再接続された状態になっています。

リモートのペリフェラルとのやり取りに関するベストプラクティスペリフェラルに再接続する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

47

Page 48: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Core Bluetoothフレームワークは、セントラル側のさまざまなトランザクションだけでなく、ペリフェラルとしての役割を実装するためにも有用です。この章では、これを的確に行うためのガイドラインやベストプラクティスを紹介します。

アドバタイズに関する検討事項ローカルデバイスにペリフェラルとしての役割を実装する上で、データのアドバタイズ機能は重要な要素です。以下の各節で、適切に実装するための考慮事項を説明します。

アドバタイズするデータの制限事項を考慮するペリフェラルのデータをアドバタイズするためには、当該データの辞書を渡して、CBPeripheralManagerクラスのstartAdvertising:メソッドを実行します(“サービスをアドバタイズする” (27 ページ)を参照)。辞書を生成する際、何をいくつアドバタイズできるか、に関して制限があることを考慮してください。

アドバタイズパケットには一般に、ペリフェラルに関するさまざまな情報を収容できますが、アドバタイズするのはデバイスのローカル名とサービスのUUIDだけです。したがって、アドバタイズ辞書のキーとして、CBAdvertisementDataLocalNameKeyとCBAdvertisementDataServiceUUIDsKeyの2つだけを指定します。他のキーを指定すればエラーになります。

さらに、アドバタイズの容量にも制限があります。アプリケーションがフォアグラウンド状態であれば、2つのアドバタイズデータキーを組み合わせて、当初は28バイト分までのアドバタイズデータを指定できます。これで不足する場合、走査に対する応答で、ローカル名に用いる10バイトを追加できます。この領域に入りきらないサービスUUIDは、特別な「オーバーフロー」領域に追加します。これを検出するためには、明示的に当該UUIDを指定して走査しなければなりません。一方、バックグラウンド状態の場合、ローカル名はアドバタイズの対象外であり、サービスUUIDはすべてオーバーフロー領域に入ります。

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

48

ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス

Page 49: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

注意: この長さには、ヘッダ情報の2バイト(新しいデータ型ごとに必要)を含みません。アドバタイズデータや応答データの具体的な形式は、Bluetooth 4.0仕様のVolume 3、Part C、Section 11に定義されています。

この制限内に収まるよう、主サービスのUUIDのみアドバタイズするようにしてください。

必要のないデータはアドバタイズしないペリフェラルのデータをアドバタイズするにはローカルデバイスの電波(および電池)を使うことになるので、他のデバイスに接続してほしいときのみ、アドバタイズを出すようにしてください。いったん接続すれば、アドバタイズパケットがなくても、データを直接調査し、やり取りできます。したがって、電波の使用を最小限に抑え、処理性能を改善し、電池の寿命を延ばすためにも、必要なくなったらアドバタイズを止めてください。これがBLEトランザクション本来の使い方です。アドバタイズを止めるには、CBPeripheralManagerクラスのstopAdvertisingメソッドを使います。

[myPeripheralManager stopAdvertising];

アドバタイズを出すか否かユーザが判断できるようにするアドバタイズを出すべきか否か、ユーザにしか判断できないことも少なくありません。たとえば、近くに他のBLE機器がないと分かっている場合、アドバタイズしても無意味です。これをアプリケーションが判断するのは難しいので、ユーザが判断できるよう、適当なユーザインターフェイスを設けるとよいでしょう。

特性を設定する可変の特性に対しては、プロパティ、値、操作権限を設定することになります。これによって、セントラルがどのようにアクセスし、特性値をやり取りするか、が決まります。特性のプロパティや操作権限は、アプリケーションの必要性に応じて設定してください。以下、次の2通りを想定して、いくつかガイダンスを示します。

● セントラルによる特性値の通知申し込みを受け付ける場合

● 重要な特性値について、ペアリングしたセントラルからのアクセス以外を拒否する場合

ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス特性を設定する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

49

Page 50: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

通知の申し込みに対応できるよう特性を設定する“頻繁に変化する特性については、値の変化を通知するよう申し込む” (43 ページ)で説明したように、頻繁に変化する(リモートペリフェラルのサービスの)特性値については、通知機能を用いるよう推奨します。できるだけ、特性値の変化を通知するよう、セントラルが申し込めるようにしてください。

可変の特性を生成する際、通知の申し込みに対応できるようにするためには、特性のプロパティとして定数CBCharacteristicPropertyNotifyを指定します。

myCharacteristic = [[CBMutableCharacteristic alloc]

initWithType:myCharacteristicUUID

properties:CBCharacteristicPropertyRead | CBCharacteristicPropertyNotify

value:nil permissions:CBAttributePermissionsReadable];

この例に示した特性値は読み取り可能であり、セントラルからの通知申し込みにも対応できます。

重要なデータについて、ペアリングした機器からのアクセスのみを許可する用途によっては、特性値のやり取りに際して、セキュリティを考慮しなければならないかも知れません。たとえばソーシャルメディアサービスを考えてみましょう。このサービスでは、会員の名前や電子メールアドレスなど、個人情報を特性として扱うかも知れません。そして、電子メールアドレスについては、信頼性を確認したデバイスからのアクセスしか許可しない、という要件も考えられます。

これを実現するためには、特性のプロパティと操作権限を適切に設定する必要があるでしょう。そのコード例を示します。

emailCharacteristic = [[CBMutableCharacteristic alloc]

initWithType:emailCharacteristicUUID

properties:CBCharacteristicPropertyRead

| CBCharacteristicPropertyNotifyEncryptionRequired

value:nil permissions:CBAttributePermissionsReadEncryptionRequired];

この例では、信頼できるデバイスにしか読み取りや通知を許可しないよう、特性を設定しました。リモートのセントラルは、接続後、特性値を読み取ろうと(または通知を申し込もうと)します。するとCore Bluetoothは、ローカルのペリフェラルとペアリング手続きをして、信頼性を確認しようと試みます。

ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス特性を設定する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

50

Page 51: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

セントラルとペリフェラルがどちらもiOSデバイスであれば、両方に、この手続きを行う旨の画面が現れます。セントラルの画面に現れているコードを、ペリフェラルのテキストフィールドに正しく入力すれば、手続きは完了です。

ペリフェラルはこのセントラルが信頼できるものと判断し、暗号化を施した特性値へのアクセスを許可します。

ローカルデバイスをペリフェラルとしてセットアップするためのベストプラクティス特性を設定する

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

51

Page 52: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

この表は「Core Bluetoothプログラミングガイド」の改訂履歴です。

メモ

iOS 7およびOS X v10.9に合わせて、バックグラウンドで長時間にわたるアクションを実行する方法や、周辺機器(ペリフェラル)を取得する新しいメソッドについての情報を改訂しました。

日付

2013-09-18

新規資料。Core Bluetoothフレームワークを使って、BLE(BluetoothLow Energy)技術を活用したアプリケーションを開発する方法の解説。

2013-08-08

2013-09-18 | Copyright © 2013 Apple Inc. All Rights Reserved.

52

書類の改訂履歴

Page 53: Core Bluetoothプログラミングガイド (TP40013257 0.0.0)

Apple Inc.Copyright © 2013 Apple Inc.All rights reserved.

本書の一部あるいは全部を Apple Inc. から書面による事前の許諾を得ることなく複写複製(コピー)することを禁じます。また、製品に付属のソフトウェアは同梱のソフトウェア使用許諾契約書に記載の条件のもとでお使いください。書類を個人で使用する場合に限り1 台のコンピュータに保管すること、またその書類にアップルの著作権表示が含まれる限り、個人的な利用を目的に書類を複製することを認めます。

Apple ロゴは、米国その他の国で登録されたApple Inc. の商標です。

キーボードから入力可能な Apple ロゴについても、これを Apple Inc. からの書面による事前の許諾なしに商業的な目的で使用すると、連邦および州の商標法および不正競争防止法違反となる場合があります。

本書に記載されているテクノロジーに関しては、明示または黙示を問わず、使用を許諾しません。 本書に記載されているテクノロジーに関するすべての知的財産権は、Apple Inc.が保有しています。 本書は、Apple ブランドのコンピュータ用のアプリケーション開発に使用を限定します。

本書には正確な情報を記載するように努めました。 ただし、誤植や制作上の誤記がないことを保証するものではありません。

Apple Inc.1 Infinite LoopCupertino, CA 95014U.S.A.

Apple Japan〒106-6140 東京都港区六本木 6 丁目10番1号 六本木ヒルズ http://www.apple.com/jp

Offline copy. Trademarks go here.

Apple Inc. は本書の内容を確認しておりますが、本書に関して、明示的であるか黙示的であるかを問わず、その品質、正確さ、市場性、または特定の目的に対する適合性に関して何らかの保証または表明を行うものではありません。その結果、本書は「現状有姿のまま」提供され、本書の品質または正確さに関連して発生するすべての損害は、購入者であるお客様が負うものとします。いかなる場合も、Apple Inc. は、本書の内容に含まれる瑕疵または不正確さによって生じる直接的、間接的、特殊的、偶発的、または結果的損害に対する賠償請求には一切応じません。そのような損害の可能性があらかじめ指摘されている場合においても同様です。上記の損害に対する保証および救済は、口頭や書面によるか、または明示的や黙示的であるかを問わず、唯一のものであり、その他一切の保証にかわるものです。 Apple Inc. の販売店、代理店、または従業員には、この保証に関する規定に何らかの変更、拡張、または追加を加える権限は与えられていません。一部の国や地域では、黙示あるいは偶発的または結果的損害に対する賠償の免責または制限が認められていないため、上記の制限や免責がお客様に適用されない場合があります。 この保証はお客様に特定

の法的権利を与え、地域によってはその他の権利がお客様に与えられる場合もあります。