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

相关推荐
jiang_bluetooth2 天前
GFPS扩展技术原理(八)-可听设备控制
蓝牙·gfps·fast pair·谷歌快速配对
jiang_bluetooth3 天前
GFPS扩展技术原理(七)-音频切换消息流
蓝牙·gfps·fast pair·谷歌快速连接
jiang_bluetooth20 天前
Bluetooth LE AUDIO架构概述
架构·蓝牙·ble audio·le audio
WPG大大通21 天前
芯驰X9SP与汽车麦克风-打造无缝驾驶体验
车载系统·汽车·硬件工程·蓝牙·开发板·麦克风
byte轻骑兵22 天前
【0x0019】HCI_Remote_Name_Request详解
蓝牙·通信协议·hci
byte轻骑兵24 天前
【0x0001】HCI_Set_Event_Mask详解
蓝牙·通信协议·hci
宋者为王1 个月前
【朝花夕拾】蓝牙&WiFi常识篇
蓝牙·p2p·热点·ap·wifi直连
AscendKing1 个月前
uniapp对接蓝牙
uni-app·蓝牙
再遇当年1 个月前
小米运动健康与华为运动健康在苹手机ios系统中无法识别蓝牙状态 (如何在ios系统中开启 蓝牙 相册 定位 通知 相机等功能权限,保你有用)
ios·蓝牙·智能手表·权限·苹果手机·小米手表·小米运动健康
SuperHeroWu71 个月前
【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 (三)
华为·蓝牙·harmonyos·鸿蒙·低功耗蓝牙·ble