Android プラットフォームは Bluetooth ネットワーク スタックをサポートしています。これにより、デバイスは他の Bluetooth デバイスとワイヤレスでデータを交換できます。アプリ フレームワークでは、Android Bluetooth API を介して Bluetooth 機能にアクセスできます。これらの API を使用すると、アプリは他の Bluetooth デバイスにワイヤレス接続し、ポイントツーポイントおよびマルチポイントの無線機能を実現できます。
Bluetooth API を使用すると、Android アプリは次のことができます。
- 他の Bluetooth デバイスをスキャンする
- ペア設定された Bluetooth デバイスのローカル Bluetooth アダプターをクエリする
- RFCOMM チャネルの確立
- サービス ディスカバリを介して他のデバイスに接続する
- 他のデバイスとの間でデータを転送する
- 複数の接続を管理する
このページでは、従来の Bluetooth に焦点を当てています。ストリーミングや Android デバイス間の通信など、バッテリー消費量の多い操作には、クラシック Bluetooth が適しています。低消費電力の要件がある Bluetooth デバイス向けに、Android 4.3(API レベル 18)では Bluetooth Low Energy の API サポートが導入されています。詳細については、Bluetooth Low Energy をご覧ください。
このドキュメントでは、ヘルスデバイス プロファイルを含む、さまざまな Bluetooth プロファイルについて説明します。次に、Android Bluetooth API を使用して、Bluetooth を使用した通信に必要な 4 つの主要タスク(Bluetooth の設定、ペア設定されたデバイスまたはローカルエリアで使用可能なデバイスの検出、デバイスの接続、デバイス間のデータ転送)を実行する方法について説明します。
基本情報
Bluetooth 対応デバイスが相互にデータを送信するには、まずペアリングプロセスを使用して通信チャネルを形成する必要があります。1 つのデバイス(検出可能なデバイス)は、受信接続リクエストに対して自身を使用可能にします。別のデバイスが、サービス ディスカバリ プロセスを使用して検出可能なデバイスを検出します。検出可能なデバイスがペア設定リクエストを受け入れると、2 つのデバイスはボンディング プロセスを完了し、セキュリティ キーを交換します。デバイスは後で使用するためにこれらのキーをキャッシュに保存します。ペア設定とボンディングのプロセスが完了すると、2 つのデバイスは情報を交換します。セッションが完了すると、ペア設定リクエストを開始したデバイスは、検出可能なデバイスにリンクしていたチャンネルを解放します。ただし、2 つのデバイスはボンドされたままになるため、今後のセッション中に自動的に再接続できます。ただし、これらのデバイスが互いに通信範囲内にあり、どちらのデバイスもボンドを除去していないことが条件となります。
Bluetooth の権限
アプリで Bluetooth 機能を使用するには、2 つの権限を宣言する必要があります。最初のメソッドは BLUETOOTH
です。接続のリクエスト、接続の受け入れ、データ転送などの Bluetooth 通信を行うには、この権限が必要です。
他に宣言する必要がある権限は ACCESS_FINE_LOCATION
です。Bluetooth スキャンを使用してユーザーの位置情報を収集できるため、アプリにこの権限が必要になります。この情報は、ユーザーが所有するデバイスだけでなく、店舗や交通機関などの場所で使用されている Bluetooth ビーコンから得られることもあります。
Android 10 以降で実行されるサービスは、ACCESS_BACKGROUND_LOCATION
権限がない限り、Bluetooth デバイスを検出できません。この要件の詳細については、バックグラウンドでの位置情報へのアクセスをご覧ください。
次のコード スニペットは、権限を確認する方法を示しています。
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(baseContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), PERMISSION_CODE) } }
Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(baseContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( MyActivity.this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, PERMISSION_CODE) } }
この権限要件の例外は、Android 11 以降を搭載したデバイスにアプリがインストールされ、コンパニオン デバイスのペア設定を使用してデバイスを関連付けている場合です。この場合、デバイスが関連付けられると、アプリは位置情報の利用許可がなくても、関連付けられている Bluetooth デバイスをスキャンできます。
Android 8.0(API レベル 26)以降を搭載したデバイスでは、位置情報の利用許可がなくても、CompanionDeviceManager
を使用することで、アプリに代わって付近のコンパニオン デバイスをスキャンできます。このオプションの詳細については、コンパニオン デバイスのペア設定をご覧ください。
注: アプリが Android 9(API レベル 28)以前をターゲットとしている場合は、ACCESS_FINE_LOCATION
権限の代わりに ACCESS_COARSE_LOCATION
権限を宣言できます。
アプリでデバイスの検出を開始したり、Bluetooth 設定を操作したりする場合は、BLUETOOTH
権限に加えて BLUETOOTH_ADMIN
権限を宣言する必要があります。ほとんどのアプリは、ローカルの Bluetooth デバイスを検出する機能のためにのみ、この権限を必要とします。この権限によって付与されるその他の能力は、アプリがユーザーのリクエストに応じて Bluetooth 設定を変更する「電源マネージャー」である場合を除き、使用しないでください。
アプリのマニフェスト ファイルで Bluetooth 権限を宣言します。たとえば、以下の場合です。
<manifest ... > <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- If your app targets Android 9 or lower, you can declare ACCESS_COARSE_LOCATION instead. --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... </manifest>
アプリの権限の宣言について詳しくは、<uses-permission> のリファレンスをご覧ください。
プロフィールを操作する
Android 3.0 以降、Bluetooth API は Bluetooth プロファイルの操作をサポートしています。Bluetooth プロファイルは、デバイス間で Bluetooth ベースの通信を行うためのワイヤレス インターフェース仕様です。一例として、Hands-Free プロファイルがあります。スマートフォンをワイヤレス ヘッドセットに接続するには、両方のデバイスがハンズフリー プロファイルをサポートしている必要があります。
Android Bluetooth API には、次の Bluetooth プロファイルの実装が用意されています。
- ヘッドセット: ヘッドセット プロファイルは、スマートフォンで使用する Bluetooth ヘッドセットをサポートします。Android には、Bluetooth ヘッドセット サービスを制御するためのプロキシである
BluetoothHeadset
クラスが用意されています。これには、Bluetooth ヘッドセットとハンズフリー(v1.5)の両方のプロファイルが含まれます。BluetoothHeadset
クラスは AT コマンドをサポートしています。このトピックの詳細については、ベンダー固有の AT コマンドをご覧ください。 - A2DP。Advanced Audio Distribution Profile(A2DP)プロファイルは、Bluetooth 接続を介してデバイス間で高品質のオーディオをストリーミングする方法を定義します。Android には、Bluetooth A2DP サービスを制御するためのプロキシである
BluetoothA2dp
クラスが用意されています。 - Health Device:Android 4.0(API レベル 14)では、Bluetooth ヘルス デバイス プロファイル(HDP)のサポートが導入されています。これにより、心拍数モニター、血液計、体温計、体重計など、Bluetooth をサポートする健康機器と Bluetooth で通信するアプリを作成できます。サポートされているデバイスと、それぞれに対応するデバイスデータ スペシャライゼーション コードのリストについては、Bluetooth の HDP デバイスデータ スペシャライゼーションをご覧ください。これらの値は、ISO/IEEE 11073-20601 [7] 仕様の命名コードの付録でも MDC_DEV_SPEC_PROFILE_* として参照されています。HDP の詳細については、Health Device Profile をご覧ください。
プロフィールに関する基本的な手順は次のとおりです。
- Bluetooth の設定の説明に沿って、デフォルトのアダプターを取得します。
BluetoothProfile.ServiceListener
を設定します。このリスナーは、サービスとの接続または接続解除をBluetoothProfile
クライアントに通知します。getProfileProxy()
を使用して、プロファイルに関連付けられているプロファイル プロキシ オブジェクトへの接続を確立します。以下の例では、プロファイル プロキシ オブジェクトはBluetoothHeadset
のインスタンスです。onServiceConnected()
で、プロファイル プロキシ オブジェクトに対するハンドルを取得します。- プロファイル プロキシ オブジェクトを取得したら、それを使用して接続の状態をモニタリングし、そのプロファイルに関連するその他のオペレーションを実行できます。
たとえば、次のコード スニペットは、BluetoothHeadset
プロキシ オブジェクトに接続して、ヘッドセット プロファイルを制御する方法を示しています。
Kotlin
var bluetoothHeadset: BluetoothHeadset? = null // Get the default adapter val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() private val profileListener = object : BluetoothProfile.ServiceListener { override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = proxy as BluetoothHeadset } } override fun onServiceDisconnected(profile: Int) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = null } } } // Establish connection to the proxy. bluetoothAdapter?.getProfileProxy(context, profileListener, BluetoothProfile.HEADSET) // ... call functions on bluetoothHeadset // Close proxy connection after use. bluetoothAdapter?.closeProfileProxy(BluetoothProfile.HEADSET, bluetoothHeadset)
Java
BluetoothHeadset bluetoothHeadset; // Get the default adapter BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); private BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = (BluetoothHeadset) proxy; } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { bluetoothHeadset = null; } } }; // Establish connection to the proxy. bluetoothAdapter.getProfileProxy(context, profileListener, BluetoothProfile.HEADSET); // ... call functions on bluetoothHeadset // Close proxy connection after use. bluetoothAdapter.closeProfileProxy(bluetoothHeadset);
ベンダー固有の AT コマンド
Android 3.0(API レベル 11)以降では、ヘッドセットが送信する事前定義されたベンダー固有の AT コマンド(Plantronics +XEVENT コマンドなど)のシステム ブロードキャストを受信するようにアプリを登録できます。たとえば、アプリは接続済みデバイスのバッテリー残量を示すブロードキャストを受信し、必要に応じてユーザーに通知したり、その他のアクションを実行したりできます。ヘッドセットのベンダー固有の AT コマンドを処理する ACTION_VENDOR_SPECIFIC_HEADSET_EVENT
インテントのブロードキャスト レシーバを作成します。
ヘルスデバイスのプロファイル
Android 4.0(API レベル 14)では、Bluetooth ヘルスデバイス プロファイル(HDP)のサポートが導入されています。これにより、心拍数モニター、血液計、体温計、体重計など、Bluetooth をサポートする健康機器と Bluetooth で通信するアプリを作成できます。Bluetooth Health API には、BluetoothHealth
クラス、BluetoothHealthCallback
クラス、BluetoothHealthAppConfiguration
クラスが含まれています。これらのクラスについては、鍵クラスとインターフェースをご覧ください。
Bluetooth Health API を使用する場合は、次の HDP の主なコンセプトを理解しておくことをおすすめします。
- ソース
- Android スマートフォンやタブレットなどのスマート デバイスに医療データを送信する健康デバイス(体重計、血糖測定器、体温計など)。
- シンク
- 医療データを受け取るスマート デバイス。Android HDP アプリの場合、シンクは
BluetoothHealthAppConfiguration
オブジェクトで表されます。 - 登録
- 特定の健康機器と通信するためにシンクを登録するために使用されるプロセス。
- つながり
- 健康機器(ソース)とスマート デバイス(シンク)の間でチャネルを開くために使用されるプロセス。
HDP アプリケーションを作成する
Android HDP アプリの作成に関する基本的な手順は次のとおりです。
BluetoothHealth
プロキシ オブジェクトへの参照を取得します。通常のヘッドセットや A2DP プロファイル デバイスと同様に、
BluetoothProfile.ServiceListener
とHEALTH
プロファイル タイプを指定してgetProfileProxy()
を呼び出して、プロファイル プロキシ オブジェクトとの接続を確立する必要があります。BluetoothHealthCallback
を作成し、ヘルスシンクとして機能するアプリケーション構成(BluetoothHealthAppConfiguration
)を登録します。ヘルスデバイスへの接続を確立します。
注: デバイスによっては、接続が自動的に開始されます。そのようなデバイスでは、この手順を行う必要はありません。
- ヘルスデバイスに正常に接続されたら、ファイル記述子を使用してヘルスデバイスの読み取りと書き込みを行います。受信したデータは、IEEE 11073 仕様を実装したヘルス マネージャーを使用して解釈する必要があります。
- 完了したら、Health チャンネルを閉じてアプリケーションの登録を解除します。また、非アクティブが長期間続いた場合も、チャネルはクローズされます。
Bluetooth を設定する
アプリが Bluetooth で通信する前に、デバイスで Bluetooth がサポートされているか、サポートされている場合は有効になっていることを確認します。
Bluetooth がサポートされていない場合は、すべての Bluetooth 機能を適切に無効にする必要があります。Bluetooth はサポートされているものの、無効になっている場合は、アプリを離れることなく、Bluetooth を有効にするようユーザーにリクエストできます。この設定は、BluetoothAdapter
を使用して次の 2 つのステップで行うことができます。
BluetoothAdapter
を取得します。BluetoothAdapter
は、あらゆる Bluetooth アクティビティに必要です。BluetoothAdapter
を取得するには、静的なgetDefaultAdapter()
メソッドを呼び出します。これにより、デバイス独自の Bluetooth アダプター(Bluetooth 無線通信)を表すBluetoothAdapter
が返されます。システム全体に 1 つの Bluetooth アダプターがあり、アプリはこのオブジェクトを使用して操作できます。getDefaultAdapter()
がnull
を返す場合、デバイスは Bluetooth をサポートしていません。次に例を示します。Kotlin
val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter() if (bluetoothAdapter == null) { // Device doesn't support Bluetooth }
Java
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // Device doesn't support Bluetooth }
- Bluetooth を有効にします。
次に、Bluetooth が有効になっていることを確認します。
isEnabled()
を呼び出して、Bluetooth が現在有効になっているかどうかを確認します。このメソッドが false を返した場合、Bluetooth は無効になっています。Bluetooth の有効化をリクエストするには、startActivityForResult()
を呼び出して、ACTION_REQUEST_ENABLE
インテントのアクションを渡します。この呼び出しは、アプリを停止せずに、システム設定から Bluetooth を有効にするリクエストを発行します。次に例を示します。Kotlin
if (bluetoothAdapter?.isEnabled == false) { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) }
Java
if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
図 1 に示すように、Bluetooth を有効にするためのユーザー権限をリクエストするダイアログが表示されます。ユーザーが「はい」と応答すると、システムは Bluetooth の有効化を開始し、プロセスが完了(または失敗)すると、アプリにフォーカスが戻ります。
図 1: Bluetooth の有効化ダイアログstartActivityForResult()
に渡されるREQUEST_ENABLE_BT
定数は、0 より大きいローカルで定義された整数です。この定数は、onActivityResult()
の実装でrequestCode
パラメータとして渡されます。Bluetooth の有効化が成功すると、アクティビティは
onActivityResult()
コールバックでRESULT_OK
結果コードを受け取ります。エラーのため Bluetooth が有効でなかった場合(またはユーザーが「いいえ」と応答した場合)、結果コードはRESULT_CANCELED
です。
必要に応じて、アプリは ACTION_STATE_CHANGED
ブロードキャスト インテントをリッスンすることもできます。このインテントは、Bluetooth 状態が変化するたびにシステムがブロードキャストします。このブロードキャストには、追加フィールド EXTRA_STATE
と EXTRA_PREVIOUS_STATE
が含まれており、それぞれ新しい Bluetooth 状態と古い Bluetooth 状態が含まれています。これらの追加フィールドで使用できる値は STATE_TURNING_ON
、STATE_ON
、STATE_TURNING_OFF
、STATE_OFF
です。このブロードキャストのリッスンは、Bluetooth の状態に加えられたランタイムの変更をアプリで検出する必要がある場合に役立ちます。
ヒント: 検出の許可を有効にすると、Bluetooth が自動的に有効になります。Bluetooth アクティビティを実行する前にデバイスの検出可能性を一貫して有効にする場合は、上記のステップ 2 をスキップできます。詳細については、このページの検出可能性を有効にするをご覧ください。
デバイスの検索
BluetoothAdapter
を使用すると、デバイス検出によって、またはペア設定されたデバイスのリストをクエリして、リモート Bluetooth デバイスを見つけることができます。
デバイス検出とは、ローカルエリアで Bluetooth 対応デバイスを検索し、各デバイスの情報を要求するスキャン手順です。このプロセスは、検出、照会、スキャンと呼ばれることもあります。ただし、付近の Bluetooth デバイスが検出リクエストに応答するのは、そのデバイスが現在「検出可能」な状態で情報リクエストを受け入れている場合に限られます。デバイスが検出可能な場合、検出リクエストに応答して、デバイス名、クラス、一意の MAC アドレスなどの情報を共有します。この情報を使用して、検出プロセスを実行しているデバイスは、検出されたデバイスへの接続を開始することを選択できます。
検出可能なデバイスからユーザーの位置情報が公開される可能性があるため、デバイス検出プロセスでは位置情報へのアクセスが必要です。Android 8.0(API レベル 26)以降を搭載しているデバイスでアプリを使用している場合は、Companion Device Manager API を使用します。この API は、アプリに代わってデバイスの検出を実行するため、アプリで位置情報の利用許可をリクエストする必要はありません。
リモート デバイスと初めて接続すると、ペア設定リクエストが自動的にユーザーに表示されます。デバイスがペア設定されると、そのデバイスに関する基本情報(デバイス名、クラス、MAC アドレスなど)が保存され、Bluetooth API を使用して読み取ることができます。リモート デバイスの既知の MAC アドレスを使用すると、デバイスが範囲内にあれば、検出を行うことなくいつでもその MAC アドレスを使用して接続を開始できます。
ペア設定と接続には違いがあります。
- ペアリングとは、2 つのデバイスが互いの存在を認識し、認証に使用できる共有リンクキーを持ち、相互に暗号化された接続を確立できることを意味します。
- 「接続」とは、現在デバイスが RFCOMM チャネルを共有し、相互にデータを送信できることを意味します。現在の Android Bluetooth API では、RFCOMM 接続を確立する前にデバイスをペア設定する必要があります。Bluetooth API を使用して暗号化された接続を開始すると、自動的にペア設定が実行されます。
以下のセクションでは、ペア設定されたデバイスを見つける方法と、デバイスの検出を使用して新しいデバイスを検出する方法について説明します。
注: デフォルトでは、Android 搭載デバイスは検出できません。ユーザーは、システム設定を使用して一定期間デバイスを検出可能にすることができます。また、アプリは、アプリを離れることなく、検出の許可を有効にするようリクエストすることもできます。詳細については、このページの検出の許可を有効にするをご覧ください。
ペア設定されたデバイスをクエリする
デバイス検出を実行する前に、ペア設定されたデバイスのセットをクエリして、目的のデバイスがすでに認識されているかどうかを確認することをおすすめします。そのためには、getBondedDevices()
を呼び出します。これは、ペア設定されたデバイスを表す BluetoothDevice
オブジェクトのセットを返します。たとえば、次のコード スニペットに示すように、ペア設定されているすべてのデバイスを照会して、各デバイスの名前と MAC アドレスを取得できます。
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
Bluetooth デバイスとの接続を開始するために、関連付けられた BluetoothDevice
オブジェクトから必要なのは、getAddress()
を呼び出して MAC アドレスを取得することだけです。接続の作成について詳しくは、デバイスの接続をご覧ください。
注意: デバイス検出を実行すると、Bluetooth アダプターのリソースが大量に消費されます。接続するデバイスが見つかったら、接続を試す前に cancelDiscovery()
で検出を停止してください。また、デバイスに接続している間は検出を実行しないでください。検出プロセスにより、既存の接続で利用可能な帯域幅が大幅に減少します。
デバイスの検出
デバイスの検出を開始するには、startDiscovery()
を呼び出します。プロセスは非同期で、検出が正常に開始されたかどうかを示すブール値を返します。検出プロセスでは通常、約 12 秒間の照会スキャンが行われ、その後に Bluetooth 名を取得することが判明した各デバイスのページスキャンが続きます。
検出された各デバイスに関する情報を受信するには、アプリで ACTION_FOUND
インテントに BroadcastReceiver を登録する必要があります。システムは、デバイスごとにこのインテントをブロードキャストします。インテントには追加フィールド EXTRA_DEVICE
と EXTRA_CLASS
が含まれ、これらのフィールドにはそれぞれ BluetoothDevice
と BluetoothClass
が含まれます。次のコード スニペットは、デバイスが検出されたときにブロードキャストを処理するように登録する方法を示しています。
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
Bluetooth デバイスとの接続を開始するために、関連付けられた BluetoothDevice
オブジェクトから必要なのは、getAddress()
を呼び出して MAC アドレスを取得することだけです。接続の作成について詳しくは、デバイスの接続をご覧ください。
注意: デバイス検出を実行すると、Bluetooth アダプターのリソースが大量に消費されます。接続するデバイスが見つかったら、接続を試す前に cancelDiscovery()
で検出を停止してください。また、デバイスに接続している間は検出を実行しないでください。検出プロセスにより、既存の接続で利用可能な帯域幅が大幅に減少します。
検出の許可を有効にする
ローカル デバイスを他のデバイスから検出可能にするには、ACTION_REQUEST_DISCOVERABLE
インテントを指定して startActivityForResult(Intent, int)
を呼び出します。これにより、設定アプリに移動せずにシステムの検出可能モードを有効にするリクエストが発行されます。これにより、自分のアプリが停止します。デフォルトでは、デバイスは 120 秒間(2 分間)検出可能となります。EXTRA_DISCOVERABLE_DURATION
エクストラを追加することで、異なる時間(最大 3,600 秒(1 時間))を定義できます。
注意: EXTRA_DISCOVERABLE_DURATION
エクストラの値を 0 に設定すると、デバイスは常に検出可能になります。この構成は安全性が低いため、おすすめしません。
次のコード スニペットでは、デバイスを 5 分間(300 秒)検出可能に設定しています。
Kotlin
val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivity(discoverableIntent)
Java
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent);
図 2 に示すように、デバイスを検出可能にする許可をユーザーにリクエストするダイアログが表示されます。ユーザーが「はい」と応答すると、デバイスは指定された時間、検出可能になります。次に、アクティビティは onActivityResult()
コールバックへの呼び出しを受け取ります。結果コードは、デバイスが検出可能である期間と同じになります。ユーザーが「いいえ」と応答した場合、またはエラーが発生した場合、結果コードは RESULT_CANCELED
です。
注: デバイスで Bluetooth が有効になっていない場合、デバイスを検出可能にすると、Bluetooth が自動的に有効になります。
デバイスは指定された時間、通知なく検出可能モードのままになります。検出可能なモードが変更されたときに通知を受け取るには、ACTION_SCAN_MODE_CHANGED
インテントに BroadcastReceiver を登録します。このインテントには追加フィールド EXTRA_SCAN_MODE
と EXTRA_PREVIOUS_SCAN_MODE
があり、それぞれ新しいスキャンモードと古いスキャンモードを提供します。各エクストラの有効な値は次のとおりです。
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- デバイスが検出可能モードになっています。
SCAN_MODE_CONNECTABLE
- デバイスは検出可能モードではないが、接続を受信できる状態である。
SCAN_MODE_NONE
- デバイスが検出可能モードではなく、接続を受信できません。
リモート デバイスへの接続を開始する場合は、デバイスの検出を有効にする必要はありません。検出の許可の有効化は、受信接続を受け入れるサーバー ソケットをアプリでホストする場合にのみ必要です。リモート デバイスは、他のデバイスへの接続を開始する前に、他のデバイスを検出できる必要があるためです。
デバイスの接続
2 つのデバイス間の接続を作成するには、一方のデバイスがサーバー ソケットを開く必要があり、もう一方のデバイスはサーバー デバイスの MAC アドレスを使用して接続を開始する必要があるため、サーバー側とクライアント側の両方のメカニズムを実装する必要があります。サーバー デバイスとクライアント デバイスは、それぞれ異なる方法で必要な BluetoothSocket
を取得します。サーバーは受信接続が受け入れられると、ソケット情報を受け取ります。クライアントは、サーバーに対して RFCOMM チャネルを開くときにソケット情報を提供します。
サーバーとクライアントは、同じ RFCOMM チャネル上でそれぞれ接続されている BluetoothSocket
を接続している場合、相互接続しているとみなされます。この時点で、各デバイスは入出力ストリームを取得し、データ転送を開始できます。これについては、接続を管理するのセクションをご覧ください。このセクションでは、2 つのデバイス間で接続を開始する方法について説明します。
接続方法
実装方法の 1 つは、各デバイスをサーバーとして自動的に準備し、各デバイスでサーバー ソケットを開いて接続をリッスンするようにすることです。この場合、どちらかのデバイスがもう片方のデバイスとの接続を開始して、クライアントになります。または、一方のデバイスで接続を明示的にホストし、オンデマンドでサーバー ソケットをオープンして、もう一方のデバイスで接続を開始することもできます。
注: 2 台のデバイスが以前にペア設定されていない場合、図 3 に示すように、Android フレームワークは接続手順中にペア設定リクエスト通知またはダイアログを自動的にユーザーに表示します。 そのため、アプリはデバイスを接続しようとする際に、デバイスがペア設定されているかどうかを考慮する必要はありません。ユーザーが 2 つのデバイスを正常にペア設定するまで RFCOMM 接続はブロックされます。ユーザーがペア設定を拒否した場合、またはペア設定プロセスが失敗またはタイムアウトした場合は、接続の試行が失敗します。
サーバーとして接続
2 つのデバイスを接続する場合、一方のデバイスは開いている BluetoothServerSocket
を保持してサーバーとして動作する必要があります。サーバー ソケットの目的は、受信接続リクエストをリッスンし、リクエストの受け入れ後に接続された BluetoothSocket
を提供することです。BluetoothSocket
を BluetoothServerSocket
から取得すると、デバイスが追加の接続を受け入れる場合を除き、BluetoothServerSocket
は破棄できます(破棄する必要があります)。
サーバー ソケットを設定して接続を受け入れるには、次の手順を完了します。
listenUsingRfcommWithServiceRecord()
を呼び出してBluetoothServerSocket
を取得します。この文字列はサービスの識別可能な名前で、デバイス上の新しいサービス ディスカバリ プロトコル(SDP)データベース エントリに自動的に書き込まれます。名前は任意で、簡単にアプリケーション名を指定できます。Universally Unique Identifier(UUID)も SDP エントリに含まれ、クライアント デバイスとの接続の合意の基礎を形成します。つまり、クライアントはこのデバイスと接続しようとすると、接続するサービスを一意に識別する UUID を受け取ります。接続が受け入れられるには、これらの UUID が一致している必要があります。
UUID は、情報を一意に識別するために使用される、文字列 ID の標準化された 128 ビット形式です。UUID の重要な点は、任意のランダムな ID を選択できる十分な大きさであり、他の ID と競合しないことです。この場合は、アプリの Bluetooth サービスを一意に識別するために使用されます。アプリケーションで使用する UUID を取得するには、ウェブ上で多くのランダムな UUID 生成ツールのいずれかを使用して、
fromString(String)
でUUID
を初期化します。- 接続リクエストのリッスンを開始するには、
accept()
を呼び出します。これはブロッキング呼び出しです。接続が受け入れられたか、例外が発生したときに返されます。接続が受け入れられるのは、リモート デバイスが、このリスニング サーバー ソケットに登録された UUID と一致する UUID を含む接続リクエストを送信した場合のみです。成功すると、
accept()
は接続されたBluetoothSocket
を返します。 - 追加の接続を受け入れる場合を除き、
close()
を呼び出します。このメソッド呼び出しは、サーバー ソケットとそのすべてのリソースを解放しますが、
accept()
によって返された接続済みBluetoothSocket
は閉じません。TCP/IP とは異なり、RFCOMM ではチャネルごとに一度に 1 つの接続クライアントしか許可されないため、ほとんどの場合、接続されたソケットを受け入れた直後にBluetoothServerSocket
でclose()
を呼び出すのが合理的です。
accept()
呼び出しはブロッキング呼び出しであるため、アプリが他のユーザーの操作に引き続き応答できるように、メイン アクティビティの UI スレッドでは実行しないでください。通常、BluetoothServerSocket
または BluetoothSocket
を含むすべての作業は、アプリケーションによって管理される新しいスレッドで行うのが合理的です。accept()
などのブロックされた呼び出しを中止するには、BluetoothServerSocket
または BluetoothSocket
に対して別のスレッドから close()
を呼び出します。BluetoothServerSocket
または BluetoothSocket
のすべてのメソッドはスレッドセーフです。
例
受信接続を受け入れるサーバー コンポーネントの簡略化したスレッドを次に示します。
Kotlin
private inner class AcceptThread : Thread() { private val mmServerSocket: BluetoothServerSocket? by lazy(LazyThreadSafetyMode.NONE) { bluetoothAdapter?.listenUsingInsecureRfcommWithServiceRecord(NAME, MY_UUID) } override fun run() { // Keep listening until exception occurs or a socket is returned. var shouldLoop = true while (shouldLoop) { val socket: BluetoothSocket? = try { mmServerSocket?.accept() } catch (e: IOException) { Log.e(TAG, "Socket's accept() method failed", e) shouldLoop = false null } socket?.also { manageMyConnectedSocket(it) mmServerSocket?.close() shouldLoop = false } } } // Closes the connect socket and causes the thread to finish. fun cancel() { try { mmServerSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } }
Java
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { // Use a temporary object that is later assigned to mmServerSocket // because mmServerSocket is final. BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code. tmp = bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's listen() method failed", e); } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned. while (true) { try { socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "Socket's accept() method failed", e); break; } if (socket != null) { // A connection was accepted. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket); mmServerSocket.close(); break; } } } // Closes the connect socket and causes the thread to finish. public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } }
この例では、受信接続が 1 つだけ必要なため、接続が受け入れられ BluetoothSocket
が取得されるとすぐに、アプリは取得した BluetoothSocket
を別のスレッドに渡して BluetoothServerSocket
を閉じてループから抜けます。
accept()
が BluetoothSocket
を返す場合、ソケットはすでに接続されています。したがって、クライアント側から行うように、connect()
を呼び出さないでください。
アプリ固有の manageMyConnectedSocket()
メソッドは、データ転送用のスレッドを開始するように設計されています。これについては、接続を管理するのセクションをご覧ください。
通常は、受信接続のリッスンが完了したらすぐに BluetoothServerSocket
を閉じる必要があります。この例では、BluetoothSocket
が取得されるとすぐに close()
が呼び出されます。サーバー ソケットでのリッスンを停止する必要がある場合にプライベート BluetoothSocket
をクローズできるパブリック メソッドをスレッド内に用意することもできます。
クライアントとして接続
オープン サーバー ソケットで接続を受け入れているリモート デバイスとの接続を開始するには、まず、リモート デバイスを表す BluetoothDevice
オブジェクトを取得する必要があります。BluetoothDevice
の作成方法については、デバイスの検索をご覧ください。次に、BluetoothDevice
を使用して BluetoothSocket
を取得し、接続を開始する必要があります。
基本的な手順は次のとおりです。
BluetoothDevice
を使用して、createRfcommSocketToServiceRecord(UUID)
を呼び出してBluetoothSocket
を取得します。このメソッドは、クライアントが
BluetoothDevice
に接続できるようにBluetoothSocket
オブジェクトを初期化します。ここで渡される UUID は、サーバー デバイスがlistenUsingRfcommWithServiceRecord(String, UUID)
を呼び出してBluetoothServerSocket
を開く際に使用する UUID と一致する必要があります。一致する UUID を使用するには、UUID 文字列をアプリケーションにハードコードし、サーバーコードとクライアントコードの両方から参照します。connect()
を呼び出して接続を開始します。なお、このメソッドはブロッキング呼び出しです。クライアントがこのメソッドを呼び出すと、システムは SDP 検索を実行して、一致する UUID を持つリモート デバイスを見つけます。ルックアップが成功し、リモート デバイスが接続を受け入れると、接続中に使用する RFCOMM チャネルが共有され、
connect()
メソッドが戻ります。接続が失敗した場合、またはconnect()
メソッドが(約 12 秒後に)タイムアウトした場合、メソッドはIOException
をスローします。connect()
はブロッキング呼び出しであるため、この接続プロシージャは、常にメイン アクティビティ(UI)スレッドとは別のスレッドで実行する必要があります。注:
connect()
を呼び出す前に、必ずcancelDiscovery()
を呼び出して、デバイスがデバイスの検出を実行していないことを確認する必要があります。検出が進行中の場合、接続の試行は非常に遅く、失敗する可能性が高くなります。
例
Bluetooth 接続を開始するクライアント スレッドの基本的な例を次に示します。
Kotlin
private inner class ConnectThread(device: BluetoothDevice) : Thread() { private val mmSocket: BluetoothSocket? by lazy(LazyThreadSafetyMode.NONE) { device.createRfcommSocketToServiceRecord(MY_UUID) } public override fun run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter?.cancelDiscovery() mmSocket?.use { socket -> // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. socket.connect() // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(socket) } } // Closes the client socket and causes the thread to finish. fun cancel() { try { mmSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the client socket", e) } } }
Java
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket // because mmSocket is final. BluetoothSocket tmp = null; mmDevice = device; try { // Get a BluetoothSocket to connect with the given BluetoothDevice. // MY_UUID is the app's UUID string, also used in the server code. tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "Socket's create() method failed", e); } mmSocket = tmp; } public void run() { // Cancel discovery because it otherwise slows down the connection. bluetoothAdapter.cancelDiscovery(); try { // Connect to the remote device through the socket. This call blocks // until it succeeds or throws an exception. mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and return. try { mmSocket.close(); } catch (IOException closeException) { Log.e(TAG, "Could not close the client socket", closeException); } return; } // The connection attempt succeeded. Perform work associated with // the connection in a separate thread. manageMyConnectedSocket(mmSocket); } // Closes the client socket and causes the thread to finish. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the client socket", e); } } }
このスニペットでは、接続の試行が行われる前に cancelDiscovery()
が呼び出されています。常に connect()
の前に cancelDiscovery()
を呼び出す必要があります。これは、現在デバイスの検出が進行中かどうかにかかわらず、cancelDiscovery()
は成功するためです。ただし、デバイスの検出が進行中かどうかをアプリで判断する必要がある場合は、isDiscovering()
を使用して確認できます。
アプリ固有の manageMyConnectedSocket()
メソッドは、データ転送用のスレッドを開始するように設計されています。これについては、接続の管理に関するセクションをご覧ください。
BluetoothSocket
による作業が完了したら、必ず close()
を呼び出します。これを行うと、接続されたソケットがすぐに閉じられ、関連するすべての内部リソースが解放されます。
接続を管理する
複数のデバイスが正常に接続されると、各デバイスに BluetoothSocket
が接続されます。デバイス間で情報を共有できるので、ここからがもっと楽しくなります。BluetoothSocket
を使用してデータを転送する一般的な手順は次のとおりです。
getInputStream()
とgetOutputStream()
を使用して、それぞれソケットを介した伝送を処理するInputStream
とOutputStream
を取得します。read(byte[])
とwrite(byte[])
を使用して、ストリームに対するデータの読み取りと書き込みを行う。
もちろん、検討すべき実装の詳細もあります。特に、ストリームからの読み取りとストリームへの書き込みには、専用のスレッドを使用する必要があります。read(byte[])
メソッドと write(byte[])
メソッドの両方が呼び出しをブロックしているため、このことは重要です。read(byte[])
メソッドは、ストリームから読み取るものが見つかるまでブロックします。通常、write(byte[])
メソッドはブロックされませんが、リモート デバイスによる read(byte[])
の呼び出し速度が十分でなく、その結果中間バッファがいっぱいになった場合はフロー制御をブロックできます。そのため、スレッドのメインループは InputStream
からの読み取り専用にする必要があります。スレッド内の個別のパブリック メソッドを使用して、OutputStream
への書き込みを開始できます。
例
Bluetooth 経由で接続された 2 つのデバイス間でデータを転送する方法の例を次に示します。
Kotlin
private const val TAG = "MY_APP_DEBUG_TAG" // Defines several constants used when transmitting messages between the // service and the UI. const val MESSAGE_READ: Int = 0 const val MESSAGE_WRITE: Int = 1 const val MESSAGE_TOAST: Int = 2 // ... (Add other message types here as needed.) class MyBluetoothService( // handler that gets info from Bluetooth service private val handler: Handler) { private inner class ConnectedThread(private val mmSocket: BluetoothSocket) : Thread() { private val mmInStream: InputStream = mmSocket.inputStream private val mmOutStream: OutputStream = mmSocket.outputStream private val mmBuffer: ByteArray = ByteArray(1024) // mmBuffer store for the stream override fun run() { var numBytes: Int // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) { // Read from the InputStream. numBytes = try { mmInStream.read(mmBuffer) } catch (e: IOException) { Log.d(TAG, "Input stream was disconnected", e) break } // Send the obtained bytes to the UI activity. val readMsg = handler.obtainMessage( MESSAGE_READ, numBytes, -1, mmBuffer) readMsg.sendToTarget() } } // Call this from the main activity to send data to the remote device. fun write(bytes: ByteArray) { try { mmOutStream.write(bytes) } catch (e: IOException) { Log.e(TAG, "Error occurred when sending data", e) // Send a failure message back to the activity. val writeErrorMsg = handler.obtainMessage(MESSAGE_TOAST) val bundle = Bundle().apply { putString("toast", "Couldn't send data to the other device") } writeErrorMsg.data = bundle handler.sendMessage(writeErrorMsg) return } // Share the sent message with the UI activity. val writtenMsg = handler.obtainMessage( MESSAGE_WRITE, -1, -1, bytes) writtenMsg.sendToTarget() } // Call this method from the main activity to shut down the connection. fun cancel() { try { mmSocket.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } } }
Java
public class MyBluetoothService { private static final String TAG = "MY_APP_DEBUG_TAG"; private Handler handler; // handler that gets info from Bluetooth service // Defines several constants used when transmitting messages between the // service and the UI. private interface MessageConstants { public static final int MESSAGE_READ = 0; public static final int MESSAGE_WRITE = 1; public static final int MESSAGE_TOAST = 2; // ... (Add other message types here as needed.) } private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private byte[] mmBuffer; // mmBuffer store for the stream public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams; using temp objects because // member streams are final. try { tmpIn = socket.getInputStream(); } catch (IOException e) { Log.e(TAG, "Error occurred when creating input stream", e); } try { tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "Error occurred when creating output stream", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { mmBuffer = new byte[1024]; int numBytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs. while (true) { try { // Read from the InputStream. numBytes = mmInStream.read(mmBuffer); // Send the obtained bytes to the UI activity. Message readMsg = handler.obtainMessage( MessageConstants.MESSAGE_READ, numBytes, -1, mmBuffer); readMsg.sendToTarget(); } catch (IOException e) { Log.d(TAG, "Input stream was disconnected", e); break; } } } // Call this from the main activity to send data to the remote device. public void write(byte[] bytes) { try { mmOutStream.write(bytes); // Share the sent message with the UI activity. Message writtenMsg = handler.obtainMessage( MessageConstants.MESSAGE_WRITE, -1, -1, bytes); writtenMsg.sendToTarget(); } catch (IOException e) { Log.e(TAG, "Error occurred when sending data", e); // Send a failure message back to the activity. Message writeErrorMsg = handler.obtainMessage(MessageConstants.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString("toast", "Couldn't send data to the other device"); writeErrorMsg.setData(bundle); handler.sendMessage(writeErrorMsg); } } // Call this method from the main activity to shut down the connection. public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "Could not close the connect socket", e); } } } }
コンストラクタが必要なストリームを取得した後、スレッドは InputStream
からデータが来るのを待ちます。read(byte[])
がストリームのデータを返すと、データは親クラスのメンバー Handler
を使用してメイン アクティビティに送信されます。スレッドは、InputStream
からさらにバイトが読み取られるのを待機します。
データの送信は、メイン アクティビティからスレッドの write()
メソッドを呼び出し、送信するバイトを渡すだけで簡単に行うことができます。このメソッドは write(byte[])
を呼び出して、リモート デバイスにデータを送信します。write(byte[])
の呼び出し時に IOException
がスローされると、スレッドはメイン アクティビティにトーストを送信し、指定されたバイトを他のデバイス(接続済み)に送信できなかったことをユーザーに伝えます。
スレッドの cancel()
メソッドを使用すると、BluetoothSocket
を閉じることで、いつでも接続を終了できます。このメソッドは、Bluetooth 接続の使用が終了したら常に呼び出す必要があります。
Bluetooth API の使用方法について詳しくは、Bluetooth Chat サンプルアプリをご覧ください。
キークラスとインターフェース
すべての Bluetooth API は、android.bluetooth
パッケージに含まれています。Bluetooth 接続の作成に必要なクラスとインターフェースの概要は次のとおりです。
BluetoothAdapter
- ローカル Bluetooth アダプター(Bluetooth 無線通信)を表します。
BluetoothAdapter
は、すべての Bluetooth インタラクションのエントリ ポイントです。これを使用して、他の Bluetooth デバイスの検出、ボンディングされた(ペア設定された)デバイスのリストをクエリし、既知の MAC アドレスを使用してBluetoothDevice
をインスタンス化し、他のデバイスからの通信をリッスンするBluetoothServerSocket
を作成できます。 BluetoothDevice
- リモートの Bluetooth デバイスを表します。これを使用して、
BluetoothSocket
を介してリモート デバイスとの接続をリクエストするか、デバイスに関する情報(名前、アドレス、クラス、ボンディング状態など)をクエリします。 BluetoothSocket
- Bluetooth ソケットのインターフェースを表します(TCP
Socket
に類似)。この接続ポイントにより、アプリはInputStream
とOutputStream
を使用して別の Bluetooth デバイスとデータを交換できます。 BluetoothServerSocket
- 受信リクエストをリッスンするオープンなサーバー ソケットを表します(TCP
ServerSocket
と同様)。2 つの Android デバイスを接続するには、一方のデバイスがこのクラスを使用してサーバー ソケットを開く必要があります。リモートの Bluetooth デバイスがこのデバイスへの接続リクエストを行うと、デバイスは接続を受け入れ、接続されたBluetoothSocket
を返します。 BluetoothClass
- Bluetooth デバイスの一般的な特性と機能について説明します。デバイスのクラスとサービスを定義する読み取り専用のプロパティ セットです。この情報はデバイスの種類に関する有用なヒントを提供しますが、このクラスの属性は、デバイスがサポートするすべての Bluetooth プロファイルとサービスについて説明しているとは限りません。
BluetoothProfile
- Bluetooth プロファイルを表すインターフェース。Bluetooth プロファイルは、デバイス間で Bluetooth ベースの通信を行うためのワイヤレス インターフェース仕様です。その一例が、Hands-Free プロファイルです。プロファイルについて詳しくは、プロファイルの操作をご覧ください。
BluetoothHeadset
- スマートフォンで使用する Bluetooth ヘッドセットをサポートします。これには、Bluetooth ヘッドセット プロファイルと Hands-Free(v1.5)プロファイルの両方が含まれます。
BluetoothA2dp
- : Advanced Audio Distribution Profile(A2DP)を使用して、Bluetooth 接続でデバイス間で高品質のオーディオをストリーミングする方法を定義します。
BluetoothHealth
- : Bluetooth サービスを制御する Health Device Profile プロキシを表します。
BluetoothHealthCallback
BluetoothHealth
コールバックの実装に使用する抽象クラス。このクラスを拡張して、アプリの登録状態と Bluetooth チャネル状態の変化に関する最新情報を受け取るためのコールバック メソッドを実装する必要があります。BluetoothHealthAppConfiguration
- Bluetooth Health のサードパーティ アプリがリモート Bluetooth Health デバイスと通信するために登録するアプリ構成を表します。
BluetoothProfile.ServiceListener
BluetoothProfile
プロセス間通信(IPC)クライアントを、特定のプロファイルを実行する内部サービスに接続したとき、または接続解除したときに通知するインターフェース。