Android:蓝牙设置配套设备配对

Android:蓝牙设置配套设备配对

一、概述

在搭载 Android 8.0(API 级别 26)及更高版本的设备上,配套设备配对会代表您的应用对附近的设备执行蓝牙或 Wi-Fi 扫描,而不需要 ACCESS_FINE_LOCATION 权限。这有助于最大限度地保护用户隐私。使用此方法执行配套设备(如支持 BLE 的智能手表)的初始配置。此外,配套设备配对需要启用位置信息服务。 配对配套设备不会自行创建连接,也不会启用连续扫描。应用可以使用蓝牙或 Wi-Fi 连接 API 建立连接。 配对设备后,设备可以使用 REQUEST_COMPANION_RUN_IN_BACKGROUND 和 REQUEST_COMPANION_USE_DATA_IN_BACKGROUND 权限从后台启动应用。应用还可以使用 REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND 权限从后台启动前台服务。 用户可以从列表中选择设备,并向应用授予访问该设备的权限。如果您卸载应用或调用 disassociate(),系统会撤消这些权限。如果用户不再需要配套应用的关联(例如在用户退出账号或移除已绑定的设备时),配套应用负责清除自己的关联。

二、实现配套设备配对

本部分介绍了如何使用 CompanionDeviceManager 通过蓝牙、BLE 和 Wi-Fi 将应用与配套设备配对。

指定配套设备 以下代码示例展示了如何向清单文件添加 标志。这会告知系统您的应用打算设置配套设备。

按 DeviceFilter 列出设备 您可以显示与您提供的 DeviceFilter 匹配的所有在范围内的配套设备(如图 1 所示)。如果您想将扫描范围限制为一台设备,可以将 setSingleDevice() 设为 true(如图 2 所示)。

图1 配套设备配对

图 2. 单设备配对

以下是可在 AssociationRequest 中指定的 DeviceFilter 的子类:

BluetoothDeviceFilterBluetoothLeDeviceFilterWifiDeviceFilter

这三个子类都有用于简化过滤器配置的构建器。在以下示例中,设备使用 BluetoothDeviceFilter 扫描蓝牙设备。

val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()

// Match only Bluetooth devices whose name matches the pattern.

.setNamePattern(Pattern.compile("My device"))

// Match only Bluetooth devices whose service UUID matches this pattern.

.addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null)

.build()

将 DeviceFilter 设置为 AssociationRequest,以便 CompanionDeviceManager 确定要搜索的设备类型。

val pairingRequest: AssociationRequest = AssociationRequest.Builder()

// Find only devices that match this request filter.

.addDeviceFilter(deviceFilter)

// Stop scanning as soon as one device matching the filter is found.

.setSingleDevice(true)

.build()

应用初始化 AssociationRequest 后,请对 CompanionDeviceManager 运行 associate() 函数。associate() 函数接受 AssociationRequest 和 Callback。 当 CompanionDeviceManager 定位到设备且准备好启动用户意见征求对话框时,Callback 会在 onAssociationPending 中返回 IntentSender。用户确认设备后,系统会在 onAssociationCreated 中返回设备的 AssociationInfo。如果您的应用找不到任何设备,回调会返回 onFailure 和错误消息。 在搭载 Android 13(API 级别 33)及更高版本的设备上:

val deviceManager =

requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE)

val executor: Executor = Executor { it.run() }

deviceManager.associate(pairingRequest,

executor,

object : CompanionDeviceManager.Callback() {

// Called when a device is found. Launch the IntentSender so the user

// can select the device they want to pair with.

override fun onAssociationPending(intentSender: IntentSender) {

intentSender?.let {

startIntentSenderForResult(it, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)

}

}

override fun onAssociationCreated(associationInfo: AssociationInfo) {

// An association is created.

}

override fun onFailure(errorMessage: CharSequence?) {

// To handle the failure.

}

})

在搭载 Android 12L(API 级别 32)或更低版本的设备上(已废弃):

val deviceManager =

requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE)

deviceManager.associate(pairingRequest,

object : CompanionDeviceManager.Callback() {

// Called when a device is found. Launch the IntentSender so the user

// can select the device they want to pair with.

override fun onDeviceFound(chooserLauncher: IntentSender) {

startIntentSenderForResult(chooserLauncher,

SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)

}

override fun onFailure(error: CharSequence?) {

// To handle the failure.

}

}, null)

用户选择的结果会发送回 activity 的 onActivityResult() 中的 fragment。然后,您就可以访问所选设备了。 当用户选择蓝牙设备时,应显示 BluetoothDevice。当用户选择蓝牙 LE 设备时,会遇到 android.bluetooth.le.ScanResult。当用户选择 Wi-Fi 设备时,应显示 android.net.wifi.ScanResult。

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

when (requestCode) {

SELECT_DEVICE_REQUEST_CODE -> when(resultCode) {

Activity.RESULT_OK -> {

// The user chose to pair the app with a Bluetooth device.

val deviceToPair: BluetoothDevice? =

data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)

deviceToPair?.let { device ->

device.createBond()

// Continue to interact with the paired device.

}

}

}

else -> super.onActivityResult(requestCode, resultCode, data)

}

}

查看完整示例: 在搭载 Android 13(API 级别 33)及更高版本的设备上:

private const val SELECT_DEVICE_REQUEST_CODE = 0

class MainActivity : AppCompatActivity() {

private val deviceManager: CompanionDeviceManager by lazy {

getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager

}

val mBluetoothAdapter: BluetoothAdapter by lazy {

val java = BluetoothManager::class.java

getSystemService(java)!!.adapter }

val executor: Executor = Executor { it.run() }

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

// To skip filters based on names and supported feature flags (UUIDs),

// omit calls to setNamePattern() and addServiceUuid()

// respectively, as shown in the following Bluetooth example.

val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()

.setNamePattern(Pattern.compile("My device"))

.addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null)

.build()

// The argument provided in setSingleDevice() determines whether a single

// device name or a list of them appears.

val pairingRequest: AssociationRequest = AssociationRequest.Builder()

.addDeviceFilter(deviceFilter)

.setSingleDevice(true)

.build()

// When the app tries to pair with a Bluetooth device, show the

// corresponding dialog box to the user.

deviceManager.associate(pairingRequest,

executor,

object : CompanionDeviceManager.Callback() {

// Called when a device is found. Launch the IntentSender so the user

// can select the device they want to pair with.

override fun onAssociationPending(intentSender: IntentSender) {

intentSender?.let {

startIntentSenderForResult(it, SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)

}

}

override fun onAssociationCreated(associationInfo: AssociationInfo) {

// AssociationInfo object is created and get association id and the

// macAddress.

var associationId: int = associationInfo.id

var macAddress: MacAddress = associationInfo.deviceMacAddress

}

override fun onFailure(errorMessage: CharSequence?) {

// Handle the failure.

}

)

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

when (requestCode) {

SELECT_DEVICE_REQUEST_CODE -> when(resultCode) {

Activity.RESULT_OK -> {

// The user chose to pair the app with a Bluetooth device.

val deviceToPair: BluetoothDevice? =

data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)

deviceToPair?.let { device ->

device.createBond()

// Maintain continuous interaction with a paired device.

}

}

}

else -> super.onActivityResult(requestCode, resultCode, data)

}

}

}

在搭载 Android 12L(API 级别 32)或更低版本的设备上(已废弃):

private const val SELECT_DEVICE_REQUEST_CODE = 0

class MainActivity : AppCompatActivity() {

private val deviceManager: CompanionDeviceManager by lazy {

getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

// To skip filters based on names and supported feature flags (UUIDs),

// omit calls to setNamePattern() and addServiceUuid()

// respectively, as shown in the following Bluetooth example.

val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()

.setNamePattern(Pattern.compile("My device"))

.addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null)

.build()

// The argument provided in setSingleDevice() determines whether a single

// device name or a list of them appears.

val pairingRequest: AssociationRequest = AssociationRequest.Builder()

.addDeviceFilter(deviceFilter)

.setSingleDevice(true)

.build()

// When the app tries to pair with a Bluetooth device, show the

// corresponding dialog box to the user.

deviceManager.associate(pairingRequest,

object : CompanionDeviceManager.Callback() {

override fun onDeviceFound(chooserLauncher: IntentSender) {

startIntentSenderForResult(chooserLauncher,

SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0)

}

override fun onFailure(error: CharSequence?) {

// Handle the failure.

}

}, null)

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

when (requestCode) {

SELECT_DEVICE_REQUEST_CODE -> when(resultCode) {

Activity.RESULT_OK -> {

// The user chose to pair the app with a Bluetooth device.

val deviceToPair: BluetoothDevice? =

data?.getParcelableExtra(CompanionDeviceManager.EXTRA_DEVICE)

deviceToPair?.let { device ->

device.createBond()

// Maintain continuous interaction with a paired device.

}

}

}

else -> super.onActivityResult(requestCode, resultCode, data)

}

}

}

三、配套设备配置文件

在 Android 12(API 级别 31)及更高版本中,用于管理手表等设备的配套应用可以使用配套设备配置文件,通过在配对时授予必要的权限来简化设置流程。如需了解详情,请参阅配套设备配置文件。

四、使配套应用保持唤醒状态

在 Android 12(API 级别 31)及更高版本中,您可以使用其他 API 来帮助配套应用在配套设备在范围内时保持运行。借助这些 API,您可以执行以下操作:

当配套设备处于范围内时,唤醒您的应用。 如需了解详情,请参阅 CompanionDeviceManager.startObservingDevicePresence()。保证只要配套设备保持在范围内,应用进程将继续运行。 如需了解详情,请参阅 CompanionDeviceService.onDeviceAppeared()。

你可能也喜欢

我国古代是如何进行人才招聘的?
365bet官方投注网站

我国古代是如何进行人才招聘的?

📅 07-06 👀 8748
OPPO A33全网通版开卖售1499元 双面玻璃高颜值千元机
JINS镜片质量与使用体验如何?
be365是否安全

JINS镜片质量与使用体验如何?

📅 08-12 👀 9704
[高清组图]先睹为快!俄罗斯世界杯场馆巡礼
365bet官方投注网站

[高清组图]先睹为快!俄罗斯世界杯场馆巡礼

📅 07-29 👀 1007
泥鳅苗哪里有卖的?多少钱一公斤(泥鳅苗去哪里购买)
365bet官方投注网站

泥鳅苗哪里有卖的?多少钱一公斤(泥鳅苗去哪里购买)

📅 07-02 👀 7791
老虎头简笔画+简单又漂亮又好看(精选14张)
be365是否安全

老虎头简笔画+简单又漂亮又好看(精选14张)

📅 07-01 👀 7855
考证软件app排行榜前十名
365bet官方投注网站

考证软件app排行榜前十名

📅 07-29 👀 8429
Viagen DirectPCR® Lysis Reagent (Mouse Tail)    鼠尾直接PCR裂解液
365bet官方投注网站

Viagen DirectPCR® Lysis Reagent (Mouse Tail) 鼠尾直接PCR裂解液

📅 07-22 👀 1795
konka电视怎么开机(konka电视怎么开机按键)
365bet365娱乐场

konka电视怎么开机(konka电视怎么开机按键)

📅 07-29 👀 794