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

相关推荐
小陈同学1236 小时前
PBAP协议(Phone Book Access Profile 蓝牙电话本协议)
蓝牙
马剑威(威哥爱编程)3 天前
【鸿蒙开发实战篇】HarmonyOS 6.0 蓝牙实现服务端和客户端通讯案例详解
华为·蓝牙·harmonyos
小陈同学1234 天前
HFP前置连接流程
蓝牙
小陈同学1235 天前
HFP-Enhanced Call Status & HF Indicators
蓝牙
wotaifuzao10 天前
(七)深入探讨BLE MAC 地址的隐私博弈:技术与隐私的较量
经验分享·物联网·macos·蓝牙·射频工程·ble
小陈同学12318 天前
HCI Vender command CSR8311初始化
蓝牙
赖small强1 个月前
【蓝牙】BLE 数据收发实战指南(手机 App ↔ 嵌入式 Linux/BlueZ)
linux·蓝牙·bluez·bluetoothctl·dbus-monitor·central·peripheral
hjjdebug2 个月前
蓝牙基础学习笔记
蓝牙·bluetooth
矜辰所致2 个月前
【导航】沁恒微 RISC-V 蓝牙 入门教程目录 【快速跳转】
沁恒微·蓝牙·risc-v·ble·ch585
不知名的前端专家2 个月前
uniapp安卓原生插件实现开启ble Server[外围模式]
android·uni-app·蓝牙