概述

  1. Android应用可通过Bluetooth API执行以下操作
      • 扫描其他蓝牙设备
      • 查询本地蓝牙适配器的配对蓝牙设备
      • 建立 RFCOMM 通道
      • 通过服务发现连接到其他设备
      • 与其他设备进行双向数据传输
      • 管理多个连接
  1. 蓝牙进行通信的四大必须任务
      • 设置蓝牙
      • 查找局部区域内的配对设备或可用设备
      • 连接设备
      • 在设备之间传输数据

基础知识

通信过程

  1. 配对 →
  1. 形成通信通道 →
  1. 可检测到的设备需将自己设置为可接收传入的连接请求、另一台设备会使用 服务发现 找到此可检测到的设备 →
  1. 可检测到的设备接受配对请求 →
  1. 完成绑定,交换密钥,两者缓存密钥 →
  1. 会话完成时,发起配对请求的设备发布已将其链接到可检测设备的通道,两设备仍保持绑定状态,以便以后自动重新连接

蓝牙权限

  1. BLUETOOTH: 执行任何蓝牙通信,例如请求连接、接受连接和传输数据等。
  1. ACCESS_FINE_LOCATION: 蓝牙扫描可用于手机用户信息
      • 若应用适配API ≤ 28 ,则声明 ACCESS_COARSE_LOCATION
  1. BLUETOOTH_ADMIN: (optional) 如果您想让应用启动设备发现或操纵蓝牙设置,则除了 BLUETOOTH权限以外,您还必须声明 BLUETOOTH_ADMIN权限。大多数应用只是需利用此权限发现本地蓝牙设备。除非应用是根据用户请求修改蓝牙设置的“超级管理员”,否则不应使用此权限所授予的其他功能。
在应用清单中声明蓝牙权限:
<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>

使用配置文件

蓝牙配置文件 是适用于设备间蓝牙通信的无线接口规范。
Android Bluetooth API为以下配置文件提供实现:
  • 耳机:耳机配置文件为蓝牙耳机提供支持,提供 BluetoothHeadset 类 — 用于控制蓝牙耳机服务的代理
  • A2DP:蓝牙立体声音频传输配置文件(A2DP)定义如何通过蓝牙连接和流式传输,将高质量音频从一个设备传输至另一个设备。Android提供 BluetoothA2dp 类 — 用于控制蓝牙A2DP服务的代理
  • 健康设备:蓝牙健康设备配置文件(HDP)该配置文件允许您创建应用,从而使用蓝牙与支持蓝牙功能的健康设备(例如心率监测仪、血糖仪、温度计、台秤等)进行通信。

使用配置文件的基本步骤

  1. 获取默认适配器(请参阅设置蓝牙)。
  1. 设置 BluetoothProfile.ServiceListener。此侦听器会在 BluetoothProfile 客户端连接到服务或断开服务连接时向其发送通知。
  1. 使用 getProfileProxy() 与配置文件所关联的配置文件代理对象建立连接。在以下示例中,配置文件代理对象是一个 BluetoothHeadset 实例。
  1. 在 onServiceConnected() 中,获取配置文件代理对象的句柄。
  1. 获得配置文件代理对象后,您可以用其监视连接状态,并执行与该配置文件相关的其他操作。

供应商特定的AT命令

从 Android 3.0(API 级别 11)开始,应用可注册接收耳机发送的预定义供应商特定 AT 命令(例如 Plantronics +XEVENT 命令)的系统广播。例如,应用可接收指示所连接设备电池电量的广播,并根据需要通知用户或采取其他操作。为 ACTION_VENDOR_SPECIFIC_HEADSET_EVENT  Intent 创建广播接收器,以处理耳机的供应商特定 AT 命令。

设置蓝牙

借助 BluetoothAdapter ,分两步:
  1. 获取 BluetoothAdatpter
      • 所有蓝牙Activity都需要BluetoothAdatpter
      • 获取BluetoothAdatpter,调用静态的 getDefaultAdapter() 方法,返回一个 BluetoothAdatpter 对象,表示设备自身的蓝牙适配器。
      • 整个系统只有一个蓝牙适配器,应用可使用此对象进行交互。
      • 如果 getDefaultAdapter() 返回 null ,则表示设备不支持蓝牙。
      val bluetoothAdapter: BluetoothAdapter? = Bluetooth.getDefaultAdapter() if (bluetoothAdapter == null) { // Device does not support Bluetooth }
  1. 启用蓝牙
      • 调用 isEnabled(),以检查当前是否启用蓝牙。若返回 false ,则表示处于停用状态。
      • 如要请求启用蓝牙,调用 startActivityForResult() ,传入一个 ACTION_REQUEST_ENABLE Intent操作,此调用会发出系统设置启用蓝牙的请求(无需停止应用)
      if (bluetoothAdapter?.isEnabled == false) { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) }
      • 传递给 startActivityForResult() 的 REQUEST_ENABLE_BT 常量为局部定义的整型数(必须大于 0)。系统会以 onActivityResult() 实现中的 requestCode 参数形式,向您传回该常量。
      • 如果成功启用蓝牙,您的 Activity 会在 onActivityResult() 回调中收到 RESULT_OK 结果代码。如果由于某个错误(或用户响应“No”)未成功启用蓝牙,则结果代码为 RESULT_CANCELED
  1. 监听蓝牙状态
      • 可以选择监听 ACTION_STATE_CHANGEED 广播Intent,每当蓝牙状态发生变化时,系统都会广播此Intent。
      • 此广播包含额外字段 EXTRA_STATEEXTRA_PREVIOUS_STATE ,二者分别包含新的和旧的蓝牙状态。
      • 这些额外字段可能为 STATE_TURNING_ONSTATE_ONSTATE_TURNING_OFFSTATE_OFF
提示:启用可检测性即可自动启用蓝牙。如果您计划在执行蓝牙 Activity 之前一直启用设备的可检测性,则可以跳过上述步骤 2。如需了解详情,请阅读的启用可检测性部分。

查找设备

概述

  • 利用 BluetoothAdatpter ,可以通过设备发现或查询配对设备的列表来查找远程蓝牙设备。
  • 设备发现是一个扫描过程,会搜索局部区域内已启用蓝牙功能的设备,并请求与每台设备相关的某些信息,也被称为发现、查询扫描
  • 只有在当下接受信息请求时,附近区域的蓝牙设备才会通过启用可检测性响应发现请求。
  • 如果已经启用可检测性,它会共享一些信息(例如设备名称、类及其唯一的MAC地址)来相应发现请求。借助此类信息,执行发现过程的设备可选择发起对已检测到设备的连接。

被配对与被连接区别

  • 被配对是指两台设备知晓彼此的存在,具有可用于身份验证的共享链路密钥,并且能够与彼此建立加密连接。
  • 被连接是指设备当前共享一个 RFCOMM 通道,并且能够向彼此传输数据。当前的 Android Bluetooth API 要求规定,只有先对设备进行配对,然后才能建立 RFCOMM 连接。在使用 Bluetooth API 发起加密连接时,系统会自动执行配对。

查找已配对设备

  1. 在执行设备发现之前,必须查询已配对的设备集,以连接所需设备是否处于已检测到状态。为此,调用 getBondedDevices() ,会返回一组表示已配对设备的 BluetoothDevice 对象。
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
  1. 如要发起与蓝牙设备的连接,只需从关联的 BluetoothDevice 对象中获取MAC地址,可的通过调用 getAddress() 检索此地址。有关创建连接的详情,请参阅连接设备部分。
注意:

发现设备

调用 startDiscovery() 开始发现设备。该进程为异步操作,返回一个布尔值,指示进程是否成功启动。
发现进程通常包含约12s的查询扫描,随后会对发现的每台设备进行页面扫描,以检索其蓝牙名称。
应用必须针对 ACTION_FOUND Intent注册一个 BroadcastReceiver ,以便接收每台发现的设备的相关信息。系统会为每台设备广播此Intent。Intent包含额外字段 EXTRA_DEVICEEXTRA_CLASS ,二者又分别包含 BluetoothDeviceBluetoothClass
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) }
如要发起与蓝牙设备的连接,只需从关联的 BluetoothDevice 对象中获取MAC地址,可的通过调用 getAddress() 检索此地址。有关创建连接的详情,请参阅连接设备部分。

启用可检测性

  • 启用
    • 若希望本地设备设为可被其他设备检测到,使用 ACTION_REQUEST_DISCOVERABLE Intent调用 startActivityForResult(Intent, int) ,这样便可发出启用系统可检测到模式的请求。
      默认情况加,设备处于可检测到模式的时间为120s,通过添加 EXTRA_DISCOVERABLE_DURATION Extra属性,定义不同的持续时间,最长可达3600s。若设置为0,则设备始终处于可检测到模式(安全性低,不建议使用)
      val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {     putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivity(discoverableIntent)
      此时弹出对话框,用户响应后,Activity会受到对 onActivityResult() 回调的调用。
      • 若用户响应Yes,其结果代码等于可检测到的持续时间,
      • 若用户响应No或出现错误,则结果代码为 RESULT_CANCELED
      注意:如果尚未在设备上启用蓝牙,则启用设备可检测性会自动启用蓝牙。
  • 监听
    • 可以为 ACTION_SCAN_MODE_CHANGED Intent注册BroadcastReceiver。
      此Intent包含额外字段 EXTRA_SCAN_MODEEXTRA_PREVIOUT_SCAN_MODE 二者分别提供新的和旧的扫描模式。每个Extra属性可能拥有以下值:
    • SCAN_MODE_CONNECTABLE_DISCOVERABLE 设备处于可检测到模式。
    • SCAN_MODE_CONNECTABLE 设备未处于可检测到模式,但仍能收到连接。
    • SCAN_MODE_NONE 设备未处于可检测到模式,且无法收到连接。

连接设备

概述

如果在两台设备之间创建连接,必须同时实现服务器端和客户端机制。因为其中一台设备必须开发服务器套接字,而另一台设备必须使用服务器设备的MAC地址发起连接,两者均以不同方法获得所需的 BluetoothSocket
  • 接受传入连接后,服务器会收到套接字信息。
  • 在打开与服务器相连的RFCOMM通道时,客户端会提供套接字信息。
当服务器和客户端在同一RFCOMM通道上分别拥有已连接的 BluetoothSocket 时,即可视为彼此连接。这种情况加,每台设备都能获得输入和输出的流式传输,并开始传输数据。

连接技术

  • 两种连接技术
      1. 自动将每台设备准备为一个服务器,从而使每台设备开发一个服务器套接字并侦听连接。此种情况下,任一设备都可发起与另一台设备的连接,并成为客户端
      1. 其中一台设备可显式托管连接并按需开发一个服务器套接字,而另一台设备则发起连接。
注意: 如果两台设备之前尚未配对,则在连接过程中,Android 框架会自动向用户显示配对请求通知或对话框。因此,在尝试连接设备时,您的应用无需担心设备是否已配对。
  1. 作为服务器连接
    1. 当需要连接两台设备时,其中一台设备必须保持开放的 BluetoothServerSocket ,从而充当服务器。服务器套接字涌入是监听传入的连接请求,并在接受请求后提供已连接的 BluetoothSocket 。从BluetoothServerSocket 中获取BluetoothSocket 后,应该丢弃 BluetoothServerSocket ,除非设备需要接受更多的连接。
      • 步骤
        • 通过调用 listenUsingRfcommWithServiceRecord()获取 BluetoothServerSocket
          该字符串是服务的可识别名称,系统会自动将其写入到设备上的新服务发现协议 (SDP) 数据库条目。此名称没有限制,可直接使用您的应用名称。SDP 条目中也包含通用唯一标识符 (UUID),这也是客户端设备连接协议的基础。换言之,当客户端尝试连接此设备时,它会携带 UUID,从而对其想要连接的服务进行唯一标识。为了让服务器接受连接,这些 UUID 必须互相匹配。
          UUID 是一种标准化的 128 位格式,可供字符串 ID 用来对信息进行唯一标识。UUID 的特点是其足够庞大,因此您可以选择任意随机 ID,而不会与其他任何 ID 发生冲突。在本例中,其用于对应用的蓝牙服务进行唯一标识。如要获取供应用使用的 UUID,您可以从网络上的众多随机 UUID 生成器中任选一种,然后使用 fromString(String) 初始化一个 UUID
          通过调用 accept()开始侦听连接请求。
          这是一个阻塞调用。当服务器接受连接或异常发生时,该调用便会返回。只有当远程设备发送包含 UUID 的连接请求,并且该 UUID 与使用此侦听服务器套接字注册的 UUID 相匹配时,服务器才会接受连接。连接成功后,accept()将返回已连接的 BluetoothSocket
          如果您无需接受更多连接,请调用 close()
          此方法调用会释放服务器套接字及其所有资源,但不会关闭 accept()所返回的已连接的 BluetoothSocket。与 TCP/IP 不同,RFCOMM 一次只允许每个通道有一个已连接的客户端,因此大多数情况下,在接受已连接的套接字后,您可以立即在 BluetoothServerSocket上调用 close()
      • 由于 accept() 为阻塞调用,因此不应在主Activity界面线程中执行该应用。
        • 通常,可以在应用所管理的新线程中完成刚才所提的所有工作,若要取消 accept() 等被阻塞的调用,需要通过另一个线程,在BluetoothServerSocketBluetoothSocket 上调用 close() 。请注意,BluetoothServerSocket 或 BluetoothSocket 中的所有方法都是线程安全的方法。
      • 示例 — 服务器组件可通过以下简化线程接受传入连接:
      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 // 只需要一个传入连接,因此在接受连接并获取 BluetoothSocket 之后,应用会立即将获取的 BluetoothSocket 传送到单独的线程、关闭 BluetoothServerSocket 并中断循环。 while (shouldLoop) { val socket: BluetoothSocket? = try { // 如果 accept() 返回 BluetoothSocket,则表示已连接套接字。因此,您不应像从客户端那样调用 connect()。 mmServerSocket?.accept() } catch (e: IOException) { Log.e(TAG, "Socket's accept() method failed", e) shouldLoop = false null } socket?.also { // 应用特定的 manageMyConnectedSocket() 方法旨在启动用于传输数据的线程。 manageMyConnectedSocket(it) mmServerSocket?.close() shouldLoop = false } } } // Closes the connect socket and causes the thread to finish. fun cancel() { // 通常,在完成传入连接的侦听后,您应立即关闭您的 BluetoothServerSocket。在此示例中,获取 BluetoothSocket 后会立即调用 close()。此外,您可能还希望在线程中提供一个公共方法,以便在需要停止侦听服务器套接字时关闭私有 BluetoothSocket。 try { mmServerSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } }
  1. 作为客户端连接 如果远程设备在开放服务器套接字上接受连接,则为了发起与此设备的连接,必须首先获取表示该远程设备的 BluetoothDevice 对象。然后,必须使用该对象来获取 BluetoothSocket 并发起连接
      • 步骤:
        • 使用 BluetoothDevice,通过调用 createRfcommSocketToServiceRecord(UUID) 获取 BluetoothSocket
          此方法会初始化 BluetoothSocket 对象,以便客户端连接至 BluetoothDevice。此处传递的 UUID 必须与服务器设备在调用 listenUsingRfcommWithServiceRecord(String, UUID) 开放其 BluetoothServerSocket 时所用的 UUID 相匹配。如要使用匹配的 UUID,请通过硬编码方式将 UUID 字符串写入您的应用,然后通过服务器和客户端代码引用该字符串。
          通过调用 connect() 发起连接。请注意,此方法为阻塞调用。
          当客户端调用此方法后,系统会执行 SDP 查找,以找到带有所匹配 UUID 的远程设备。如果查找成功并且远程设备接受连接,则其会共享 RFCOMM 通道以便在连接期间使用,并且 connect() 方法将会返回。如果连接失败,或者 connect() 方法超时(约 12 秒后),则此方法将引发 IOException
          由于 connect() 是阻塞调用,因此您应始终在主 Activity(界面)线程以外的线程中执行此连接步骤。
          注意:您应始终调用 cancelDiscovery(),以确保设备在您调用 connect()之前不会执行设备发现。如果正在执行发现操作,则会大幅降低连接尝试的速度,并增加连接失败的可能性。
      • 示例 — 发起蓝牙连接的客户端线程的基本示例
      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() 方法旨在启动用于传输数据的线程 manageMyConnectedSocket(socket) } } // Closes the client socket and causes the thread to finish. fun cancel() { try { // 使用完 BluetoothSocket 后,请务必调用 close()。这样,您便可立即关闭连接的套接字,并释放所有相关的内部资源。 mmSocket?.close() } catch (e: IOException) { Log.e(TAG, "Could not close the client socket", e) } } }

管理连接

成功连接多台设备后,每台设备都会有已连接的 BluetoothSocket ,可以在设备之间共享信息。
使用 BluetoothSocket 传输数据的一般过程如下:
  1. 使用 getInputStream() 和 getOutputStream(),分别获取通过套接字处理数据传输的 InputStream 和 OutputStream
  1. 使用 read(byte[]) 和 write(byte[]) 读取数据以及将其写入数据流。
具体来说,您应使用专门的线程从数据流读取数据,以及将数据写入数据流。这一点非常重要,因为 read(byte[]) 和 write(byte[]) 方法都是阻塞调用。read(byte[]) 方法将会阻塞,直至从数据流中读取数据。write(byte[]) 方法通常不会阻塞,但若远程设备调用 read(byte[]) 方法的速度不够快,进而导致中间缓冲区已满,则该方法可能会保持阻塞状态以实现流量控制。因此,线程中的主循环应专门用于从 InputStream 中读取数据。您可使用线程中单独的公共方法,发起对 OutputStream 的写入操作。
示例 — 如何在通过蓝牙连接的两台设备之间传输数据
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 // 当构造函数获取必要的数据流后,线程会等待通过 InputStream 传入的数据。当 read(byte[]) 返回数据流中的数据时,将使用来自父类的 Handler 成员将数据发送到主 Activity。然后,线程会等待从 InputStream 中读取更多字节。 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. // 发送传出数据不外乎从主 Activity 调用线程的 write() 方法,并传入要发送的字节。此方法会调用 write(byte[]),从而将数据发送到远程设备。如果在调用 write(byte[]) 时引发 IOException,则线程会发送一条 Toast 至主 Activity,向用户说明设备无法将给定的字节发送到另一台(连接的)设备。 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, mmBuffer) writtenMsg.sendToTarget() } // Call this method from the main activity to shut down the connection. // 借助线程的 cancel() 方法,您可通过关闭 BluetoothSocket 随时终止连接。当您结束蓝牙连接的使用时,应始终调用此方法。 fun cancel() { try { mmSocket.close() } catch (e: IOException) { Log.e(TAG, "Could not close the connect socket", e) } } } }
有关使用 Bluetooth API 的演示,请参阅蓝牙聊天示例应用

关键类和接口

android.bluetooth 包中提供所有 Bluetooth API。
以下概要列出了创建蓝牙连接所需的类和接口:
BluetoothAdapter表示本地蓝牙适配器(蓝牙无线装置)。BluetoothAdapter 是所有蓝牙交互的入口点。借助该类,您可以发现其他蓝牙设备、查询已绑定(已配对)设备的列表、使用已知的 MAC 地址实例化 BluetoothDevice,以及通过创建 BluetoothServerSocket 侦听来自其他设备的通信。
BluetoothDevice表示远程蓝牙设备。借助该类,您可以通过 BluetoothSocket 请求与某个远程设备建立连接,或查询有关该设备的信息,例如设备的名称、地址、类和绑定状态等。BluetoothSocket表示蓝牙套接字接口(类似于 TCP Socket)。这是允许应用使用 InputStream 和 OutputStream 与其他蓝牙设备交换数据的连接点。
BluetoothServerSocket表示用于侦听传入请求的开放服务器套接字(类似于 TCP ServerSocket)。如要连接两台 Android 设备,其中一台设备必须使用此类开放一个服务器套接字。当远程蓝牙设备向此设备发出连接请求时,该设备接受连接,然后返回已连接的 BluetoothSocket
BluetoothClass描述蓝牙设备的一般特征和功能。这是一组只读属性,用于定义设备的类和服务。虽然这些信息会提供关于设备类型的有用提示,但该类的属性未必描述设备支持的所有蓝牙配置文件和服务。
BluetoothProfile表示蓝牙配置文件的接口。蓝牙配置文件是适用于设备间蓝牙通信的无线接口规范。举个例子:免提配置文件。如需了解有关配置文件的详细讨论,请参阅使用配置文件BluetoothHeadset提供蓝牙耳机支持,以便与手机配合使用。这包括蓝牙耳机配置文件和免提 (v1.5) 配置文件。
BluetoothA2dp定义如何使用蓝牙立体声音频传输配置文件 (A2DP),通过蓝牙连接将高质量音频从一个设备流式传输至另一个设备。
BluetoothHealth表示用于控制蓝牙服务的健康设备配置文件代理。
BluetoothHealthCallback用于实现 BluetoothHealth 回调的抽象类。您必须扩展此类并实现回调方法,以接收关于应用注册状态和蓝牙通道状态变化的更新内容。BluetoothHealthAppConfiguration表示第三方蓝牙健康应用注册的应用配置,该配置旨在实现与远程蓝牙健康设备的通信。
BluetoothProfile.ServiceListener当 BluetoothProfile 进程间通信 (IPC) 客户端连接到运行特定配置文件的内部服务或断开该服务连接时,向该客户端发送通知的接口。
badge