Android低功耗蓝牙(BLE)扫描异常求助:仅获取随机地址且设备名称为null
Fixing Your Android BLE Scanning Issues
Hey there, let's tackle those BLE scanning problems you're facing. I'll break down each issue and give you actionable fixes based on your code and common BLE pitfalls.
Issues Recap
- You're only seeing random Bluetooth addresses, and
device.getName()returns null. - Your app only detects devices when another phone is running BLE advertising (via the BLE Scanner app).
Breakdown & Fixes
1. Random Addresses & Null Device Names
BLE devices commonly use random addresses (for privacy reasons) alongside public addresses—this isn't necessarily a bug. The null device name usually happens because:
- The device isn't broadcasting its name in the advertising packet, or
- The Android Bluetooth stack hasn't resolved the name yet (it may take multiple scan results).
Fix Steps:
- Check Address Type: Use
device.getType()to confirm if it's a random address (BluetoothDevice.DEVICE_TYPE_LE_RANDOM) or public. Random addresses are normal for many modern BLE devices. - Parse Scan Record Manually: If
device.getName()is null, extract the name directly from theScanResult's scan record. Add this logic to youronScanResult:@Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice device = result.getDevice(); String deviceName = device.getName(); // Fallback to parsing scan record if name is missing if (deviceName == null) { ScanRecord scanRecord = result.getScanRecord(); if (scanRecord != null) { deviceName = scanRecord.getDeviceName(); } } String address = device.getAddress(); int rssi = result.getRssi(); Toast.makeText(BluetoothActivity.this, String.format("%s | %s | RSSI: %d", address, deviceName != null ? deviceName : "Unknown", rssi), Toast.LENGTH_SHORT).show(); } - Verify Permissions: For Android 6.0+, you need
ACCESS_FINE_LOCATION(requested at runtime). For Android 12+, addBLUETOOTH_SCANandBLUETOOTH_CONNECTpermissions to your manifest and request them at runtime. Missing permissions can restrict scanning or return incomplete data.
2. Scanning Only Works When Another Phone Advertises
This is likely tied to your scan settings or device-specific scanning behavior. Here's what to adjust:
- Scan Mode: You're using
SCAN_MODE_LOW_POWER, which is optimized for background use (low battery but limited sensitivity). For foreground scanning, switch toSCAN_MODE_LOW_LATENCYto get more frequent results:ScanSettings scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // Update this line .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE) .setReportDelay(0) .build(); - Location Services: Android requires Location Services to be enabled for BLE scanning (even if you don't use location data). Make sure it's turned on in the device settings.
- Test with More Devices: Try scanning other BLE hardware (smartwatches, headphones, beacons) to rule out issues with your test device's advertising behavior. The BLE Scanner app might send a stronger/frequent advertisement that triggers your phone's scan module to detect other devices.
Additional Code Improvements
- Reuse ScanCallback: Creating a new
ScanCallbackevery time you callscanBLEDevicescan lead to reference leaks or mismatched stop/start calls. Move it to a class-level variable instead. - Enhance Error Handling: In
onScanFailed, map error codes to readable messages to diagnose issues faster:@Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); String errorMsg = switch (errorCode) { case ScanCallback.SCAN_FAILED_ALREADY_STARTED -> "Scan already running"; case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED -> "BLE scan not supported on this device"; case ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES -> "Insufficient hardware resources"; case ScanCallback.SCAN_FAILED_INTERNAL_ERROR -> "Internal scan error"; default -> "Unknown scan error: " + errorCode; }; Toast.makeText(BluetoothActivity.this, "Scan failed: " + errorMsg, Toast.LENGTH_SHORT).show(); }
Example Updated Code
Here's how your refined scan setup might look:
// Class-level variables private ScanCallback scanCallback; private Handler handler = new Handler(Looper.getMainLooper()); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize scan callback once scanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { super.onScanResult(callbackType, result); BluetoothDevice device = result.getDevice(); String deviceName = device.getName(); if (deviceName == null) { ScanRecord scanRecord = result.getScanRecord(); if (scanRecord != null) { deviceName = scanRecord.getDeviceName(); } } String address = device.getAddress(); int rssi = result.getRssi(); Toast.makeText(BluetoothActivity.this, String.format("%s | %s | RSSI: %d", address, deviceName != null ? deviceName : "Unknown", rssi), Toast.LENGTH_SHORT).show(); } @Override public void onBatchScanResults(List<ScanResult> results) { super.onBatchScanResults(results); Toast.makeText(BluetoothActivity.this, "Batch scan results received", Toast.LENGTH_SHORT).show(); } @Override public void onScanFailed(int errorCode) { super.onScanFailed(errorCode); String errorMsg = switch (errorCode) { case ScanCallback.SCAN_FAILED_ALREADY_STARTED -> "Scan already running"; case ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED -> "BLE scan not supported on this device"; case ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES -> "Insufficient hardware resources"; case ScanCallback.SCAN_FAILED_INTERNAL_ERROR -> "Internal scan error"; default -> "Unknown scan error: " + errorCode; }; Toast.makeText(BluetoothActivity.this, "Scan failed: " + errorMsg, Toast.LENGTH_SHORT).show(); } }; } public void scanBLEDevices(boolean enable) { if (bleScanner == null) { Toast.makeText(BluetoothActivity.this, "Couldn't get Scanner object", Toast.LENGTH_SHORT).show(); return; } if (enable) { ScanSettings scanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE) .setReportDelay(0) .build(); bleScanner.startScan(null, scanSettings, scanCallback); Toast.makeText(BluetoothActivity.this, "Scan Started!", Toast.LENGTH_SHORT).show(); handler.postDelayed(() -> { bleScanner.stopScan(scanCallback); Toast.makeText(BluetoothActivity.this, "Scan stopped automatically", Toast.LENGTH_SHORT).show(); }, 30000); } else { try { bleScanner.stopScan(scanCallback); Toast.makeText(BluetoothActivity.this, "Scan stopped!", Toast.LENGTH_SHORT).show(); } catch (IllegalStateException e) { Toast.makeText(BluetoothActivity.this, "Error stopping scan: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } }
Give these changes a try, and test on multiple devices to rule out device-specific quirks. Let me know if you still hit snags!
内容的提问来源于stack exchange,提问作者fattouma
相关产品推荐
相关产品推荐

