Android BLE 蓝牙查找

蓝牙,想必大家都不陌生,它是一种无线通讯技术标准,用于短距离间交换数据。

蓝牙主要分为经典蓝牙和低功耗蓝牙,蓝牙 3.0 以下版本称为经典蓝牙,功耗高,传输数据量大,有效距离 10 米左右,蓝牙 4.0 及以上为低功耗蓝牙,简称 BLE 蓝牙,功耗低,传输数据量相对较小,有效距离 50 米左右。因为现在的蓝牙基本上都是 5.0+ 了,所以这里主要讲解 BLE 蓝牙的开发。Android 4.3 为蓝牙低功耗引入内置平台支持,并提供了相应的 API 。

蓝牙权限

xml 复制代码
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

其中 ACCESS_COARSE_LOCATION 和 ACCESS_FINE_LOCATION 属于危险权限,需要动态申请,这里不再赘述。位置是必须的权限,否则是扫描不出结果的。

启用蓝牙

首先需要获取 BluetoothAdapter,它是设备的蓝牙适配器,系统只有一个蓝牙适配器,我们需要使用此对象进行交互。

kotlin 复制代码
private val bluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE) {
    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothManager.adapter
}

启用蓝牙时,需先判断一下蓝牙是否已经启用,如果没有的话则启用它。需要注意的是,这里使用的 registerForActivityResult 要写在 onCreate 方法里,不然会报错。

kotlin 复制代码
val bluetoothLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode == Activity.RESULT_OK) {
            // TODO: Bluetooth enabled successfully
        }
    }

bluetoothAdapter?.takeUnless { it.isEnabled }?.let {
    val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    bluetoothLauncher.launch(intent)
}

查找设备

因为蓝牙扫描比较耗电,所以应遵循以下准则:

  • 找到所需设备后,立即停止扫描。
  • 绝对不进行循环扫描,并设置扫描时间限制。之前可用的设备可能已超出范围,继续扫描会耗尽电池电量。
kotlin 复制代码
lifecycleScope.launch(Dispatchers.IO) {
    // 开启扫描
    bluetoothAdapter?.bluetoothLeScanner?.startScan(scanCallback)
    // 扫描时间限制
    delay(10000)
    // 停止扫描
    bluetoothAdapter?.bluetoothLeScanner?.stopScan(scanCallback)
}

这里会接收一个 ScanCallback 回调

kotlin 复制代码
private val scanCallback = object : ScanCallback() {

    // 当扫描到蓝牙设备时,这个方法会被调用。其中 callbackType 参数表示扫描类型,result 参数表示扫描到的设备信息。
    override fun onScanResult(callbackType: Int, result: ScanResult?) {
        if (result != null) {
            val device = result.device
            Log.i(TAG, "device.name:${device?.name}, address:${device.address}")
        }
    }

    // 当批量扫描到多个蓝牙设备时,这个方法会被调用。其中 results 参数表示扫描到的设备列表。
    override fun onBatchScanResults(results: MutableList<ScanResult>?) {
        Log.i(TAG, "results size: ${results?.size}")
    }

    // 当蓝牙扫描失败时,这个方法会被调用。其中 errorCode 参数表示扫描失败类型。
    override fun onScanFailed(errorCode: Int) {
        Log.i(TAG, "onScanFailed: $errorCode")
    }
    
}

在一般情况下,BLE 蓝牙只能扫描到支持 BLE 协议的设备,而不能直接扫描到传统蓝牙设备。某些设备具有双模功能,既支持传统蓝牙也支持 BLE,这样的设备可以通过 BLE 来进行扫描,并且可以同时扫描到支持 BLE 和传统蓝牙的设备。

相关推荐
byte轻骑兵1 天前
【HID】规范精讲[8]: 蓝牙HID核心之L2CAP层——无线人机交互的通信桥梁设计解析
人工智能·人机交互·蓝牙·键盘·hid
胡楚昊1 天前
借Polar IOTS一道困难挑战题简单入门蓝牙流量分析
物联网·蓝牙
byte轻骑兵1 天前
【AVRCP】规范精讲[10]:链路管理器LM互操作规则与场景落地
人工智能·音视频·蓝牙·avrcp·音视频控制
嵌入式学习_force2 天前
02_state
设计模式·蓝牙
byte轻骑兵3 天前
【HID】规范精讲[7]: 蓝牙HID底层核心——基带与LMP依赖深度解析
网络·人工智能·人机交互·蓝牙·键盘·hid
Evand J3 天前
【MATLAB代码介绍】基于RSSI的蓝牙定位程序,N个锚点、二维平面
开发语言·matlab·蓝牙·定位·rssi
MonkeyKing5 天前
蓝牙GAP通用访问协议详解:从原理到多平台实战代码
flutter·蓝牙
byte轻骑兵5 天前
【HID】规范精讲[6]: 蓝牙HID系统设计指南——从合规到体验的全维度要求
人机交互·蓝牙·键盘·鼠标·遥控·hid
yanlaifan5 天前
经典蓝牙中信道和链路的关系
蓝牙
yanlaifan7 天前
蓝牙领域中的带宽和宽带
蓝牙