Bluetooth (BLE)扫描报错error code 2,部分真机异常求助
BLE扫描errorCode 2(SCAN_FAILED_APPLICATION_REGISTRATION_FAILED)解决方案
错误码说明
errorCode 2对应官方定义的SCAN_FAILED_APPLICATION_REGISTRATION_FAILED,表示应用无法向系统注册BLE扫描客户端,通常和权限配置、系统资源限制、厂商定制ROM限制有关。
针对性解决步骤
1. 补全权限适配细节
虽然你提到Manifest权限齐全,但需分Android版本确认以下权限:
- Android 6.0+:必须动态申请
ACCESS_FINE_LOCATION(BLE扫描依赖位置服务,仅静态权限无效); - Android 10+:若需前台扫描,确保已申请
ACCESS_FINE_LOCATION,涉及后台扫描需额外申请ACCESS_BACKGROUND_LOCATION; - Android 12+:需新增
BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,若扫描不需要关联位置,可添加android:usesPermissionFlags="neverForLocation"声明。
同时必须确保系统位置服务已开启(不是仅应用权限),部分厂商设备即使给了权限,关闭系统位置开关也会导致扫描失败。
2. 修复代码逻辑问题
你的代码存在几个可能触发扫描失败的逻辑:
- 重复注册广播接收器:每次调用
scanForBeacon都会注册BluetoothAdapter.ACTION_STATE_CHANGED广播,未注销会导致重复接收事件、多次调用startScan,系统会拒绝重复注册。建议在页面销毁时注销接收器,或确保只注册一次。 - 扫描时机冲突:代码中同时在蓝牙已开启时直接启动扫描,又在广播的
STATE_ON中启动扫描,可能导致重复启动扫描请求,触发系统限制。建议统一通过广播的STATE_ON事件启动扫描。 - 重试逻辑不合理:
onScanFailed中直接关闭再开启蓝牙,频繁操作会占用系统蓝牙资源,反而更难注册。改为延迟重试扫描即可。
优化后的核心代码示例:
private BroadcastReceiver receiver; private boolean isReceiverRegistered = false; private void scanForBeacon(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { btAdapter = BluetoothAdapter.getDefaultAdapter(); if (btAdapter == null) { // 设备不支持蓝牙 return; } if(btAdapter.isEnabled()){ initScanParams(); startBleScan(); } else{ // 提示开启蓝牙 getOwnActivity().runOnUiThread(() -> { Global.showAlert(getOwnActivity(), SweetAlertDialog.ERROR_TYPE, R.string.error, R.string.must_enabled_bt_for_join_attendance, R.string.ok, sweetAlertDialog -> { dismiss(); if(timer != null) timer.cancel(); }); }); } // 仅注册一次广播接收器 if(!isReceiverRegistered){ receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); if(state == BluetoothAdapter.STATE_ON){ initScanParams(); startBleScan(); } else if(state == BluetoothAdapter.STATE_TURNING_OFF){ new Handler().postDelayed(() -> { Log.d(TAG, "bluetooth adapter try to enable"); btAdapter.enable(); }, 500); } } } }; IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); getOwnActivity().registerReceiver(receiver, filter); isReceiverRegistered = true; } } } private void initScanParams(){ beaconList = new ArrayList<>(); peripheralList = new ArrayList<>(); settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_BALANCED) // 尝试切换扫描模式 .build(); filters = new ArrayList<>(); } private void startBleScan(){ try{ mLEScanner = btAdapter.getBluetoothLeScanner(); if(mLEScanner != null){ // 先停止之前的扫描(如果存在) mLEScanner.stopScan(mScanCallback); mLEScanner.startScan(filters, settings, mScanCallback); } }catch (Exception e) { Log.e("hata", e.getMessage()); } } // 在页面销毁时注销广播 @Override public void onDestroy() { super.onDestroy(); if(isReceiverRegistered && receiver != null){ getOwnActivity().unregisterReceiver(receiver); isReceiverRegistered = false; } // 停止扫描 if(mLEScanner != null){ mLEScanner.stopScan(mScanCallback); } }
3. 适配厂商ROM限制
针对你提到的问题设备:
- Xiaomi Redmi Note 9s:
- 进入「安全中心→应用管理→你的应用→权限管理」,确保蓝牙、位置权限全部允许;
- 关闭应用的「省电优化」,将应用加入「后台运行白名单」;
- 开启系统设置的「位置信息→高精度模式」。
- Samsung A7 2017:
- 进入「设置→位置→位置服务」,确保开启并设置为「高精度」;
- 检查「设置→应用→你的应用→权限」,确认蓝牙、位置权限已授予;
- 关闭「省电模式」,避免系统限制BLE扫描。
- Tecno Spark 5 Pro (Android 10):
- 进入「设置→应用和通知→权限管理」,确认应用的蓝牙、位置权限为「允许」;
- 关闭系统的「超级省电」模式;
- 部分Tecno机型需在「开发者选项」中关闭「蓝牙扫描限制」(如果有该选项)。
4. 调整扫描参数
- 将扫描模式从
SCAN_MODE_LOW_LATENCY改为SCAN_MODE_BALANCED,高功耗模式容易被厂商ROM限制; - 尝试不传
filters和settings,直接调用mLEScanner.startScan(mScanCallback),简化扫描请求,降低系统拒绝概率。
内容的提问来源于stack exchange,提问作者zafercaliskan
相关产品推荐
相关产品推荐

