Android蓝牙搜索异常:无法检测附近Bluetooth设备技术求助
解决蓝牙设备搜索不到的问题
看起来你的代码逻辑本身没问题,但权限配置和蓝牙状态检查的缺失是导致搜不到设备的核心原因,我帮你一步步修正:
1. 补全权限配置(最关键)
Android系统从6.0开始对蓝牙扫描增加了位置权限限制,12及以上版本又新增了专属蓝牙权限,你的Manifest权限完全不够。更新你的AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.findbluetoothdemo"> <!-- 适配Android 11及以下的蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- 蓝牙扫描必须的位置权限(Android 6.0+) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 12+ 专属蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 声明设备支持蓝牙(可选但推荐) --> <uses-feature android:name="android.hardware.bluetooth" android:required="true" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2. 添加动态权限请求
光在Manifest里声明还不够,危险权限需要在代码中主动请求。在MainActivity.java中添加权限请求逻辑:
首先导入必要的包:
import android.Manifest; import android.content.pm.PackageManager; import android.os.Build; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat;
然后添加权限请求方法:
private void requestBluetoothPermissions() { String[] requiredPermissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+ 需要的权限 requiredPermissions = new String[]{ Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION }; } else { // Android 6.0-11 需要的权限 requiredPermissions = new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH }; } // 检查是否有权限,没有就请求 if (ContextCompat.checkSelfPermission(this, requiredPermissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, requiredPermissions, 100); } }
在onCreate方法末尾调用这个方法:
@Override protected void onCreate(Bundle savedInstanceState) { // ... 你的原有代码 ... registerReceiver(broadcastReceiver ,intentFilter); // 添加权限请求 requestBluetoothPermissions(); }
3. 完善蓝牙状态检查
你的代码没有检查蓝牙是否开启,也没有处理设备不支持蓝牙的情况。修改searchFunction方法:
public void searchFunction(View view) { // 先检查权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { requestBluetoothPermissions(); return; } // 检查设备是否支持蓝牙 if (bluetoothAdapter == null) { statusTextView.setText("Device doesn't support Bluetooth"); searchButton.setEnabled(false); return; } // 检查蓝牙是否开启,没开就请求开启 if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, 1); return; } // 清空旧数据,显示搜索提示 bluetoothDevices.clear(); addresses.clear(); bluetoothDevices.add("Searching for devices..."); statusTextView.setText("Searching..."); searchButton.setEnabled(false); arrayAdapter.notifyDataSetChanged(); // 如果正在扫描,先停止再重新开始 if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } bluetoothAdapter.startDiscovery(); }
另外,重写onActivityResult处理蓝牙开启后的扫描:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1) { if (resultCode == RESULT_OK) { // 蓝牙开启成功,自动开始扫描 searchFunction(searchButton); } else { statusTextView.setText("Bluetooth is required to search devices"); searchButton.setEnabled(true); } } }
4. 修复代码中的小问题
- 你原来的
searchFunction里先添加提示文字再立刻清空,导致用户看不到搜索提示,上面的代码已经调整了顺序 - 日志里的拼写错误:
Nmae改成Name,不影响功能但更规范:Log.i("Device Found","Name :"+name+" Address :"+address+" RSSI :"+rssi);
最后注意事项
- 蓝牙扫描比较耗电,建议添加超时停止逻辑,比如用
Handler延迟调用bluetoothAdapter.cancelDiscovery() - 如果你的目标是BLE(低功耗蓝牙)设备,经典蓝牙的
startDiscovery无法扫描到,需要改用BluetoothLeScannerAPI
内容的提问来源于stack exchange,提问作者TanikshG




