Android Kotlin开发BLE设备扫描无结果问题求助
解决Android BLE扫描不到设备的问题
针对BLE扫描无结果的问题,可以从以下几个关键方向排查修复:
1. 完善权限适配与检查
Android不同版本对BLE权限的要求差异很大,当前代码仅检查了ACCESS_COARSE_LOCATION,权限覆盖不全:
- Manifest权限补充:针对Android 12+添加权限标记,确保权限生效:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <!-- Android 12+ 权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> <!-- 旧版本位置权限,建议用ACCESS_FINE_LOCATION更可靠 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
- 代码中权限申请逻辑更新:一次性申请所有必要权限,避免遗漏:
fun startScan() { val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { arrayOf( Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION ) } else { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH ) } if (requiredPermissions.any { ContextCompat.checkSelfPermission(activity, it) != PackageManager.PERMISSION_GRANTED }) { ActivityCompat.requestPermissions(activity, requiredPermissions, REQUEST_PERMISSION_CODE) return } // 后续扫描逻辑... }
2. 检查蓝牙状态并请求开启
代码未确认蓝牙是否开启,这是扫描无结果的常见原因:
fun startScan() { // 先检查蓝牙适配器是否可用,以及蓝牙是否开启 if (bluetoothAdapter == null) { Log.e(TAG, "设备不支持BLE") return } if (!bluetoothAdapter!!.isEnabled) { val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT) return } // 权限检查逻辑... }
在MainActivity中添加蓝牙开启结果处理:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == BleScanner.REQUEST_ENABLE_BT) { if (resultCode == RESULT_OK) { bleScanner.startScan() } else { Log.w(TAG, "用户未开启蓝牙,无法扫描") } } }
在BleScanner的companion object中添加常量:
const val REQUEST_ENABLE_BT = 456
3. 修复扫描回调,排查设备识别问题
当前回调直接假设设备是HM-10,但部分BLE设备广播名称为空,或者名称不匹配,先打印所有扫描到的设备,同时添加扫描失败回调:
private val scanCallback = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { super.onScanResult(callbackType, result) val device = result.device // 处理名称为空的情况 val deviceName = device.name ?: "未知设备" Log.d(TAG, "扫描到设备: $deviceName (${device.address}), RSSI = ${result.rssi} dBm") // 再筛选目标HM-10设备 if ("HM-10".equals(deviceName, ignoreCase = true)) { Log.d(TAG, "找到目标设备HM-10: $deviceName (${device.address}), RSSI = ${result.rssi} dBm") } } // 必须重写此方法,排查扫描启动失败的原因 override fun onScanFailed(errorCode: Int) { super.onScanFailed(errorCode) val errorMsg = when(errorCode) { SCAN_FAILED_ALREADY_STARTED -> "扫描已启动" SCAN_FAILED_APPLICATION_REGISTRATION_FAILED -> "应用注册失败" SCAN_FAILED_FEATURE_UNSUPPORTED -> "设备不支持BLE扫描" SCAN_FAILED_INTERNAL_ERROR -> "内部错误" else -> "未知错误: $errorCode" } Log.e(TAG, "扫描失败: $errorMsg") } }
4. 修正Handler初始化
避免线程问题,使用主线程Looper初始化Handler:
// MainActivity中初始化BleScanner时 bleScanner = BleScanner(this, Handler(Looper.getMainLooper()))
5. 完善权限授权回调
确保所有必要权限都被授予后再启动扫描:
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { BleScanner.REQUEST_PERMISSION_CODE -> { val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED } if (allGranted) { bleScanner.startScan() } else { Log.w(TAG, "部分权限未授予,无法启动BLE扫描") } } } }
内容的提问来源于stack exchange,提问作者Sergio
相关产品推荐
相关产品推荐

