Android蓝牙设备搜索异常:BroadcastReceiver无法正常工作
Hey there, let's figure out why your Bluetooth device discovery isn't working. Looking at your code and logs, the main issue here is missing runtime location permissions (critical for Android 6.0+) plus a couple of small code tweaks. Let's break down the fixes step by step:
1. Remove the Unprivileged Permission
First, delete <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" /> from your AndroidManifest.xml. This permission is only available to system apps, and including it won't help your regular app—it might even cause unexpected behavior.
2. Request Location Permissions at Runtime
Starting with Android 6.0 (API 23), apps need to request ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION at runtime to scan for Bluetooth devices. Your manifest has the static permissions, but you're not asking the user to grant them.
Add this code to handle runtime permissions:
private static final int REQUEST_LOCATION_PERMISSION = 100; // Call this before starting discovery private boolean checkLocationPermissions() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION_PERMISSION); return false; } return true; } // Handle permission request result @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_LOCATION_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted, start discovery DiscoverDevice(); } else { Toast.makeText(this, "Location permission is required for Bluetooth scanning", Toast.LENGTH_SHORT).show(); } } }
Then update your DiscoverDevice() method to check permissions first:
public void DiscoverDevice(){ if (!checkLocationPermissions()) { return; // Wait for permission grant } Log.d("MainActivity", "RUNNING-1"); if (bluetoothAdapter.isDiscovering()){ Log.d("MainActivity", "RUNNING-2"); bluetoothAdapter.cancelDiscovery(); } // Register receiver BEFORE starting discovery IntentFilter discoverDevicesIntent = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mBroadcastReceiver, discoverDevicesIntent); bluetoothAdapter.startDiscovery(); Log.d("MainActivity", "RUNNING-3 (Discovery started)"); }
3. Fix BroadcastReceiver Registration & Memory Leaks
Right now you're registering the receiver every time you start discovery, which can lead to multiple registrations. Instead, register it in onResume() and unregister in onPause() to avoid leaks and ensure it's active when needed:
@Override protected void onResume() { super.onResume(); IntentFilter discoverDevicesIntent = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mBroadcastReceiver, discoverDevicesIntent); } @Override protected void onPause() { super.onPause(); try { unregisterReceiver(mBroadcastReceiver); } catch (IllegalArgumentException e) { e.printStackTrace(); } }
4. Fix the Null Pointer Exception for mBluetooth
In your onCreate() method, you're calling mBluetooth.setOnClickListener() without initializing it with findViewById. Add this line after setContentView():
mBluetooth = (Switch) findViewById(R.id.mBluetooth); // Replace with your actual Switch ID
5. Additional Checks
- Make sure the Bluetooth device you're trying to discover is set to discoverable mode (most devices don't broadcast by default).
- Verify that your phone's Bluetooth is enabled before starting the scan.
- Double-check that your
DeviceListAdapteris correctly implemented (though the main issue here is the permission and receiver timing).
After making these changes, run your app again—you should see the RUNNING-6 log and devices appearing in your list once permissions are granted and discovery starts.
内容的提问来源于stack exchange,提问作者Kacper Żołądziejewski




