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 和传统蓝牙的设备。

相关推荐
嵌入式小企鹅1 天前
蓝牙学习系列(七):BLE GATT 数据模型详解
学习·蓝牙·ble·蓝牙协议栈·蓝牙开发·gatt
zhaoshuzhaoshu2 天前
蓝牙 ACL 与 SCO 链路联系与详细区别对比
网络·物联网·蓝牙·无线
jiang_bluetooth4 天前
TWS耳机播放本地提示音以及主副耳同步流程
蓝牙·蓝牙耳机·a2dp·tws音频
zhaoshuzhaoshu4 天前
LE Audio(低功耗音频)协议架构术语全详细解析
物联网·蓝牙·无线
深念Y4 天前
蓝牙功放板改AUX输出,从差分信号到高转低的探索
蓝牙·电子·变压器·diy·魔改·aux·差分信号
Vis-Lin5 天前
BLE 协议栈:HCI ACL 数据详解
网络·物联网·网络协议·蓝牙·iot·ble
桑榆肖物5 天前
用 .NET 做一个跨平台的 Improv Wi-Fi 蓝牙配网项目
.net·蓝牙·iot
zhaoshuzhaoshu6 天前
HFP AT命令及其交互流程(包含AG与HF的场景流程)
物联网·蓝牙·无线
byte轻骑兵10 天前
【LE Audio】PACS精讲[2]: 服务层核心逻辑,玩转音频能力发布与交互
音视频·蓝牙·pacs·le audio·低功耗音频
zhaoshuzhaoshu13 天前
蓝牙音频协议与编解码介绍(含详细参数对比)
物联网·蓝牙·无线