You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BLE扫描报错代码2,添加BLUETOOTH_SCAN权限仍无法解决

BLE扫描失败错误代码2的修复方案

一、核心问题定位

错误代码2对应BluetoothAdapter.ERROR_PERMISSION_DENIED,本质是权限未正确配置或授予;Manifest中BLUETOOTH_SCAN的警告是因为targetSdkVersion未与compileSdkVersion同步为34导致的API版本兼容性提示。

二、分步修复

1. 同步build.gradle的SDK版本

确保Module级build.gradle中compileSdk和targetSdk都设置为34,消除权限声明警告:

android {
    compileSdk 34

    defaultConfig {
        // 其他配置不变
        targetSdk 34 // 必须与compileSdk版本一致
        ...
    }
}

2. 修正AndroidManifest.xml权限声明

针对API31+(Android 12及以上)的BLE扫描需求,添加正确的权限组合:

<!-- 旧版本(API30及以下)兼容权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

<!-- API31+ 扫描权限:如果需要获取iBeacon的UUID/Major/Minor,不要加neverForLocation标志 -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!-- 仅扫描基础设备信息时可添加:android:usesPermissionFlags="neverForLocation" -->

<!-- 获取BLE广播完整数据(如UUID)必须的位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- 后台扫描需求(可选):API29-32需声明,API33+需配合后台服务 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" android:maxSdkVersion="32" />

<!-- 声明App依赖BLE硬件 -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

3. 动态申请危险权限

BLUETOOTH_SCAN和ACCESS_FINE_LOCATION都是危险权限,必须在运行时申请,用户授权后才能启动扫描:

// 示例:Kotlin权限申请逻辑
private val requestPermissionsLauncher = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
    val allGranted = permissions.all { it.value }
    if (allGranted) {
        // 权限全部授予,启动BLE扫描
        startBleScan()
    } else {
        // 提示用户开启权限
        Toast.makeText(this, "需授予权限才能扫描BLE设备", Toast.LENGTH_SHORT).show()
    }
}

// 触发权限检查与申请
fun checkPermissions() {
    val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        arrayOf(
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.ACCESS_FINE_LOCATION
        )
    } else {
        arrayOf(
            Manifest.permission.BLUETOOTH_ADMIN,
            Manifest.permission.ACCESS_FINE_LOCATION
        )
    }

    val needRequest = requiredPermissions.any {
        ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED
    }

    if (needRequest) {
        requestPermissionsLauncher.launch(requiredPermissions)
    } else {
        startBleScan()
    }
}

4. 确保蓝牙与位置服务开启

  • 扫描前检查蓝牙状态,未开启则引导用户打开:
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled) {
    val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
    startActivityForResult(enableBtIntent, 1001)
}
  • 开启位置服务:即使设备不需要GPS定位,Android 10+也要求开启位置服务才能获取BLE设备的完整广播数据(如UUID、Major/Minor)。

5. 修正扫描回调的解析逻辑

如果权限配置正确但仍返回空值,检查ScanCallback中广播数据的解析逻辑是否正确,示例iBeacon数据解析:

@Override
public void onScanResult(int callbackType, ScanResult result) {
    super.onScanResult(callbackType, result);
    ScanRecord record = result.getScanRecord();
    if (record == null) return;

    byte[] scanBytes = record.getBytes();
    // 验证iBeacon广播格式(前缀0x02 0x15)
    if (scanBytes.length >= 25 && scanBytes[0] == 0x02 && scanBytes[1] == 0x15) {
        // 提取UUID
        byte[] uuidBytes = Arrays.copyOfRange(scanBytes, 2, 18);
        String uuid = bytesToUuid(uuidBytes);
        // 提取Major/Minor
        int major = ((scanBytes[18] & 0xFF) << 8) | (scanBytes[19] & 0xFF);
        int minor = ((scanBytes[20] & 0xFF) << 8) | (scanBytes[21] & 0xFF);
        // 提取RSSI、TxPower
        int rssi = result.getRssi();
        int txPower = scanBytes[22];
        long timestamp = System.currentTimeMillis();

        // 组装JSON数据
        Map<String, Object> bleData = new HashMap<>();
        bleData.put("uuid", uuid);
        bleData.put("major", major);
        bleData.put("minor", minor);
        bleData.put("rssi", rssi);
        bleData.put("txPower", txPower);
        bleData.put("timestamp", timestamp);
        // 添加到结果列表
    }
}

private String bytesToUuid(byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.length; i++) {
        sb.append(String.format("%02X", bytes[i]));
        if (i == 3 || i == 5 || i == 7 || i == 9) sb.append("-");
    }
    return sb.toString().toLowerCase();
}

三、验证步骤

  1. 确认build.gradle的compileSdk和targetSdk均为34
  2. 检查Manifest权限声明符合上述要求
  3. 运行App,确认权限申请弹窗出现并授权
  4. 开启蓝牙和位置服务
  5. 启动扫描,检查JSON数据是否包含有效UUID、RSSI等信息

内容的提问来源于stack exchange,提问作者CUCOOPE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:02:11