Android CompanionDeviceManager从未找到任何附近的蓝牙设备

siv3szwd  于 2022-12-21  发布在  Android
关注(0)|答案(1)|浏览(260)

我试图利用Android的CompanionDeviceManager API在我运行Android 13的Pixel 5上查找附近的蓝牙(非LE)设备,但它似乎只找到附近的WiFi网络.我怀疑deviceFilter工作不正常.
最初,我配置BluetoothDeviceFilter的代码如下所示:

private val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
    // Match only Bluetooth devices whose name matches the pattern
    .setNamePattern(Pattern.compile("(?i)\\b(Certain Device Name)\\b"))
    .build()

private val pairingRequest: AssociationRequest = AssociationRequest.Builder()
    // Find only devices that match our request filter
    .addDeviceFilter(deviceFilter)
    // Don't stop scanning as soon as one device matching the filter is found.
    .setSingleDevice(false)
    .build()

但是,使用此代码时,没有设备出现在系统生成的配套设备配对屏幕中。

考虑到我的正则表达式可能无意中限制过多,我将过滤器更改为使用允许所有内容的正则表达式,如下所示:
.setNamePattern(Pattern.compile(".*"))
但即使是这个过滤器也无法允许附近的任何蓝牙设备出现在配对屏幕中。
当我故意不添加任何过滤器时,我看到的都是WiFi网络,所以配套设备管理器可以工作,它似乎只是蓝牙结果配置错误。

private val pairingRequest: AssociationRequest = AssociationRequest.Builder()
    // No filter, let's see it all!
    .setSingleDevice(false)
    .build()

使用Android操作系统的系统蓝牙菜单,我清楚地看到有蓝牙设备在我的设备范围内,我甚至可以连接到他们,但相同的设备从来没有出现在我的应用程序。
我做错了什么导致附近的蓝牙设备不显示在我的CompanionDeviceManager配对屏幕上?
代码如下:
kt类家庭片段:片段(){

//Filter visible Bluetooth devices so only Mozis within range are displayed
private val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder()
    // Match only Bluetooth devices whose name matches the pattern.
    .setNamePattern(Pattern.compile(BLUETOOTH_DEVICE_NAME_REGEX_TO_FILTER_FOR))
    .build()

private val pairingRequest: AssociationRequest = AssociationRequest.Builder()
    // Find only devices that match this request filter.
    .addDeviceFilter(deviceFilter)
    // Don't stop scanning as soon as one device matching the filter is found.
    .setSingleDevice(false)
    .build()

private val deviceManager: CompanionDeviceManager by lazy {
    requireContext().getSystemService(Context.COMPANION_DEVICE_SERVICE) as CompanionDeviceManager
}

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

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {

    setupPairingButton()

}

/**
 * This callback listens for the result of connection attempts to our Mozi Bluetooth devices
 */
@Deprecated("Deprecated in Java")
@SuppressLint("MissingPermission")
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?.createBond()
            }
        }
        else -> super.onActivityResult(requestCode, resultCode, data)
    }
}

private fun setupPairingButton() {
    binding.buttonPair.setOnClickListener {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            /**
             * This is the approach to show a pairing dialog for Android 33+
             */
            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 { sender ->
                            activity?.let { fragmentActivity ->
                                startIntentSenderForResult(
                                    fragmentActivity,
                                    sender,
                                    SELECT_DEVICE_REQUEST_CODE,
                                    null,
                                    0,
                                    0,
                                    0,
                                    null
                                )
                            }
                        }
                    }

                    override fun onAssociationCreated(associationInfo: AssociationInfo) {
                        // Association created.

                        // AssociationInfo object is created and get association id and the
                        // macAddress.
                        var associationId = associationInfo.id
                        var macAddress: MacAddress? = associationInfo.deviceMacAddress
                    }

                    override fun onFailure(errorMessage: CharSequence?) {
                        // Handle the failure.
                        showBluetoothErrorMessage(errorMessage)
                    }
                })
        } else {
            /**
             * This is the approach to show a pairing dialog for Android 32 and below
             */

            // 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,
                            null
                        )
                    }

                    override fun onFailure(error: CharSequence?) {
                        // Handle the failure.
                       showBluetoothErrorMessage(error)
                    }
                }, null
            )
        }
    }
}

companion object {
    private const val SELECT_DEVICE_REQUEST_CODE = 0
    private const val BLUETOOTH_DEVICE_NAME_REGEX_TO_FILTER_FOR = "(?i)\\bCertain Device Name\\b"
}}

Android清单

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<!-- Bluetooth Permissions -->
<uses-feature android:name="android.software.companion_device_setup" android:required="true"/>
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission android:name="android.permission.BLUETOOTH"
    android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
    android:maxSdkVersion="30" />

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Needed only if your app looks for Bluetooth devices.
     If your app doesn't use Bluetooth scan results to derive physical
     location information, you can strongly assert that your app
     doesn't derive physical location. -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags= "neverForLocation"
    tools:targetApi="s" />

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

...
</manifest>
tpgth1q7

tpgth1q71#

您可以尝试使用一个空的BluetoothDeviceFilter,如下所示:

private val deviceFilter: BluetoothDeviceFilter = BluetoothDeviceFilter.Builder().build()

以向API发出您需要蓝牙设备的信号,并查看是否至少手机能看到您的设备。
然后,您可以再次尝试名称过滤器,这次添加一个带有BluetoothDeviceFilter.Builder.addServiceUuid的服务UUID过滤器。
如果您不知道设备的UUID或者不想将其用作过滤器,可以使用任意一个UUID并将掩码设置为全零(文档建议使用空值也可以)。
这是一个很蹩脚的解决方案,但它可能会帮助您更进一步

相关问题