Android中BLUETOOTH_SCAN等蓝牙权限请求失败,求解答
问题原因及解决方案
你的蓝牙权限请求失败、不弹出对话框的核心原因是Android 12+(API 31)对蓝牙权限的特殊要求未满足,具体问题点和修复步骤如下:
1. 权限声明缺失关键属性
Android 12及以上新增的BLUETOOTH_SCAN、BLUETOOTH_CONNECT、BLUETOOTH_ADVERTISE权限需要额外配置:
- 若
BLUETOOTH_SCAN仅用于扫描蓝牙设备不需要获取位置信息,必须添加android:usesPermissionFlags="neverForLocation"属性,否则系统会判定你需定位权限,导致请求异常。 - 旧版本(API 30及以下)的蓝牙权限需添加
android:maxSdkVersion="30"做兼容,避免权限冲突。
修改后的Manifest权限声明:
<!-- Android 12+ 新蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <!-- Android 11及以下 旧蓝牙权限(仅兼容用) --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-feature android:name="android.hardware.bluetooth" android:required="true" /> <!-- 若需通过蓝牙扫描获取位置,需添加定位权限 --> <!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> -->
2. TargetSdkVersion 未达标
只有当App的targetSdkVersion设置为31或更高时,Android系统才会识别新的蓝牙权限并允许动态请求。若targetSdkVersion低于31,系统会将新蓝牙权限映射为旧的正常权限(无需动态申请),导致调用requestPermissions时直接返回拒绝,且不弹出请求框。
修改Module级build.gradle(或build.gradle.kts):
android { defaultConfig { targetSdkVersion 33 // 至少设置为31 // 其他配置... } }
3. 权限请求逻辑优化
你的代码中方法名requestStoragePermission属于命名错误(实际请求蓝牙权限),虽不影响功能,但建议修正以提升可读性。同时需兼容旧版本设备的权限逻辑:
// 修正方法名 @RequiresApi(api = Build.VERSION_CODES.S) private void requestBluetoothScanPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.BLUETOOTH_SCAN)) { new AlertDialog.Builder(this) .setTitle("需要权限") .setMessage("此权限用于扫描蓝牙设备") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, BLUETOOTH_PERMISSION_CODE); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create().show(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, BLUETOOTH_PERMISSION_CODE); } }
同时在点击事件中添加版本判断,兼容旧设备:
buttonRequest.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12+ 处理新权限 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, "你已拥有此权限!", Toast.LENGTH_SHORT).show(); } else { requestBluetoothScanPermission(); } } else { // Android 11及以下 处理旧权限 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, "你已拥有此权限!", Toast.LENGTH_SHORT).show(); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN}, BLUETOOTH_PERMISSION_CODE); } } } });
完成以上修改后,重新打包安装App,即可正常触发蓝牙权限请求对话框。
内容的提问来源于stack exchange,提问作者AdamPI
相关产品推荐
相关产品推荐

