You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Android BLE ScanFilter通过UUID筛选蓝牙打印机?

问题原因分析

你遇到的核心问题是BLE扫描过滤器无法过滤经典蓝牙服务UUID:

  • 你目标的UUID 00001101-0000-1000-8000-00805f9b34fb 是经典蓝牙的串口服务(SPP)UUID,属于BR/EDR协议范畴,并非BLE GATT服务UUID。
  • BLE扫描过滤器ScanFilter的setServiceUuid是基于BLE设备广播包中携带的GATT服务UUID进行过滤的,经典蓝牙设备不会在BLE广播中携带SPP的UUID,因此过滤条件永远不匹配,onScanResult无回调。
  • fetchUuidsWithSdp()是经典蓝牙的API,用于查询设备的SDP服务记录,这也是你能通过它拿到目标UUID的原因,但这个操作和BLE扫描过滤是完全独立的流程。
解决方案

放弃使用BLE扫描过滤器,改为扫描所有设备后,通过SDP查询验证目标UUID:

1. 修改扫描逻辑,移除过滤器

启动扫描时不要传入ScanFilter,先获取所有可扫描到的设备:

val settings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_BALANCED).build()
handler.postDelayed({
    bluetoothAdapter.bluetoothLeScanner.stopScan(bleCallback)
}, 15000)
bluetoothAdapter.bluetoothLeScanner.startScan(null, settings, bleCallback)

2. 通过广播接收SDP查询结果

fetchUuidsWithSdp()是异步操作,需要注册广播接收器来接收查询完成的回调:

// 在Activity/Fragment中注册广播接收器
private val uuidReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val device = intent?.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
        val uuids = intent?.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID)?.map { it as ParcelUuid }
        
        uuids?.forEach { parcelUuid ->
            if (parcelUuid.uuid.toString() == "00001101-0000-1000-8000-00805f9b34fb") {
                // 找到目标蓝牙打印机
                Log.i(TAG, "找到目标设备: ${device?.name}")
                // 这里可以停止扫描或进行后续操作
                bluetoothAdapter.bluetoothLeScanner.stopScan(bleCallback)
            }
        }
    }
}

// 在onCreate中注册
registerReceiver(uuidReceiver, IntentFilter(BluetoothDevice.ACTION_UUID))

3. 修改ScanCallback触发SDP查询

在onScanResult中调用fetchUuidsWithSdp(),并避免重复查询同一设备:

object : ScanCallback() {
    @SuppressLint("MissingPermission")
    override fun onScanResult(callbackType: Int, result: ScanResult?) {
        result?.device?.let { device ->
            // 避免重复查询同一设备,维护一个已查询设备的集合
            if (!queriedDevices.contains(device.address)) {
                queriedDevices.add(device.address)
                device.fetchUuidsWithSdp()
            }
        }
    }
    
    // 全局变量存储已查询的设备地址
    private val queriedDevices = mutableSetOf<String>()
}

4. 注销广播接收器(避免内存泄漏)

在onDestroy中注销接收器:

override fun onDestroy() {
    super.onDestroy()
    unregisterReceiver(uuidReceiver)
}
补充说明
  • 如果目标打印机仅支持经典蓝牙(不支持BLE),可以直接使用经典蓝牙的扫描API(BluetoothAdapter.startDiscovery()),而非BLE扫描API,效率更高。
  • 经典蓝牙扫描需要BLUETOOTH_SCAN权限,Android 12及以上还需要ACCESS_FINE_LOCATION权限,确保权限申请齐全。

内容的提问来源于stack exchange,提问作者rik194

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:25:19