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

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:
    1. 进入「安全中心→应用管理→你的应用→权限管理」,确保蓝牙、位置权限全部允许;
    2. 关闭应用的「省电优化」,将应用加入「后台运行白名单」;
    3. 开启系统设置的「位置信息→高精度模式」。
  • Samsung A7 2017:
    1. 进入「设置→位置→位置服务」,确保开启并设置为「高精度」;
    2. 检查「设置→应用→你的应用→权限」,确认蓝牙、位置权限已授予;
    3. 关闭「省电模式」,避免系统限制BLE扫描。
  • Tecno Spark 5 Pro (Android 10):
    1. 进入「设置→应用和通知→权限管理」,确认应用的蓝牙、位置权限为「允许」;
    2. 关闭系统的「超级省电」模式;
    3. 部分Tecno机型需在「开发者选项」中关闭「蓝牙扫描限制」(如果有该选项)。

4. 调整扫描参数

  • 将扫描模式从SCAN_MODE_LOW_LATENCY改为SCAN_MODE_BALANCED,高功耗模式容易被厂商ROM限制;
  • 尝试不传filters和settings,直接调用mLEScanner.startScan(mScanCallback),简化扫描请求,降低系统拒绝概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:25:24