BluetoothAdapter.startDiscovery()无法发现息屏的蓝牙智能手机设备问题
你现有代码的逻辑没有问题,扫描不到息屏蓝牙设备是经典蓝牙本身的机制限制导致的,具体说明和解决方案如下:
核心原因
经典蓝牙的startDiscovery()扫描仅能发现主动开启了可发现模式的设备,目前安卓、iOS等移动端系统的默认策略均为:
- 仅用户停留在系统蓝牙设置页面时,才会临时开启120秒左右的经典蓝牙可发现性
- 息屏、退出蓝牙设置页面后,系统会自动关闭可发现模式,设备不会响应经典蓝牙扫描请求,所以无法被扫描到
适配方案
方案1:继续使用经典蓝牙扫描
需要被扫描的设备主动申请开启可发现模式,无法静默触发,需要用户授权,被扫描端添加如下代码即可:
// 触发系统可发现模式申请弹窗 Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); // 参数为可发现时长,0表示永久开启(部分厂商 ROM 会限制最大时长) discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent);
用户同意授权后,设备就可以被你现有代码的startDiscovery()扫描到。
方案2:改用BLE蓝牙扫描(更推荐,符合你的全量扫描需求)
当前绝大多数智能手机开启蓝牙后默认会对外发送BLE广播,不需要开启可发现模式,息屏状态下也能被扫描到,替换为BLE扫描逻辑即可实现需求,示例代码如下:
// 声明BLE扫描回调 private ScanCallback bleScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice device = result.getDevice(); // 可根据device.getType()区分设备是经典蓝牙、BLE还是双模设备 System.out.println("发现设备:" + device.getName() + ",MAC地址:" + device.getAddress()); } }; // 开始BLE扫描 public void startBleScan(View v) { BluetoothLeScanner bleScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner(); if (bleScanner == null) { System.out.println("设备不支持BLE"); return; } // 安卓12及以上需要先申请BLUETOOTH_SCAN权限,安卓6-11需要申请定位权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_FINE_LOCATION}, 1001); return; } // 配置扫描参数,低延迟模式扫描速度更快 ScanSettings scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .build(); bleScanner.startScan(null, scanSettings, bleScanCallback); System.out.println("BLE扫描已启动"); } // 页面销毁时停止扫描,避免功耗浪费 @Override protected void onDestroy() { super.onDestroy(); BluetoothLeScanner bleScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner(); if (bleScanner != null && bleScanCallback != null) { bleScanner.stopScan(bleScanCallback); } unregisterReceiver(broadcastReceiver); }
该方案可以扫描到所有开启蓝牙的双模/ BLE设备,不受设备亮屏息屏、是否在蓝牙设置页的限制。
内容的提问来源于stack exchange,提问作者Shikhar Agrawal
相关产品推荐
相关产品推荐

