行业知识
Android 蓝牙权限申请适配全机型优化指南
前言
()蓝牙技术在现代移动应用程序中的应用越来越广泛,从连接外部设备到数据传输,都离不开蓝牙功能。在 Android 平台上,为了使用蓝牙,应用程序需要获得相应的蓝牙权限。然而,由于不同的 Android 设备和版本可能存在一些差异,正确而优雅地申请蓝牙权限成为确保应用程序兼容性的关键。本文将为你提供一个优秀的指南,以确保在各种 Android 设备上成功申请蓝牙权限。
一、了解蓝牙权限
在开始之前,首先需要了解 Android 中与蓝牙相关的权限。在清单文件(AndroidManifest.xml)中添加以下权限:
()BLUETOOTH 权限用于启用蓝牙功能
BLUETOOTH_ADMIN 权限则用于执行蓝牙操作,如发现设备、建立连接等。
BLUETOOTH_SCAN、BLUETOOTH_ADVERTISE 和 BLUETOOTH_CONNECT 权限,这些权限通常与蓝牙扫描、广播和连接相关。
添加了位置权限 ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION 和 ACCESS_BACKGROUND_LOCATION,这些权限在进行蓝牙操作时可能需要,特别是在 Android 12 中更加强调了对位置权限的访问。
BLUETOOTH 和 BLUETOOTH_ADMIN 权限的声明使用 android:maxSdkVersion=“30”,这表明这两个权限只在 Android 30 版本及以下有效,这是因为 Android 31 已经移除了这两个权限的声明要求。必须添加android:maxSdkVersion=“30”,否在在其他机型会出现java.lang.SecurityException: Need BLUETOOTH permission: Neither user 10267 nor current process has android.permission.BLUETOOTH.。使用tools:node="replace"是为了覆盖第三方SDK中的蓝牙权限,避免第三方SDK未添加android:maxSdkVersion=“30”。
二、动态请求蓝牙权限
虽然在清单文件中声明权限是必要的,但从 Android 6.0(API 级别 23)开始,系统引入了运行时权限,包括蓝牙权限。因此,需要在运行时动态请求蓝牙权限。
在代码中,我们可以通过以下方式动态请求蓝牙权限:
public class PermissionUtils { public static boolean hasPermission(Context context, String permission) { return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; } public static void requestPermission(Activity activity, String[] permission, int requestCode) { ActivityCompat.requestPermissions(activity, permission, requestCode); }} 在进行蓝牙操作之前,我们需要检查并请求蓝牙权限。以下是一个示例:
public void searchBluetoothDevice() { // 检查权限状态 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { boolean scanPermission = PermissionUtils.hasPermission(this, Manifest.permission.BLUETOOTH_SCAN); boolean advertisePermission = PermissionUtils.hasPermission(this, Manifest.permission.BLUETOOTH_ADVERTISE); boolean connectPermission = PermissionUtils.hasPermission(this, Manifest.permission.BLUETOOTH_CONNECT); if (!scanPermission || !advertisePermission || !connectPermission) { // 有一个或多个权限未授予,需要申请权限 PermissionUtils.requestPermission(this, new String[]{ Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT, }, 1001); } else { // 权限已授予,跳转到蓝牙页面 navigateToBluetoothPage(); } } else { // 处理 Android 12 之前的版本 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { checkLocationPermissions(); } else { // Android 版本低于 M,直接跳转到蓝牙页面 navigateToBluetoothPage(); } }}public void checkLocationPermissions() { // 检查权限状态 boolean locationPermission = PermissionUtils.hasPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION); boolean accessPermission = PermissionUtils.hasPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION); if (!locationPermission || !accessPermission) { // 有一个或多个权限未授予,需要申请权限 PermissionUtils.requestPermission(this, new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, }, 1002); } else { // 权限已授予,跳转到蓝牙页面 navigateToBluetoothPage(); }}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001) { // 处理蓝牙权限请求结果 if (PermissionUtils.verifyPermissions(grantResults)) { // 权限已授予,跳转到蓝牙页面 navigateToBluetoothPage(); } else { // 用户拒绝了权限请求,可以进行相应的处理 } } else if (requestCode == 1002) { // 处理位置权限请求结果 if (PermissionUtils.verifyPermissions(grantResults)) { // 权限已授予,跳转到蓝牙页面 navigateToBluetoothPage(); } else { // 用户拒绝了权限请求,可以进行相应的处理 } }}private void navigateToBluetoothPage() { Intent intent = new Intent(this, BluetoothPageActivity.class); startActivity(intent); finish();} 在蓝牙搜索设备之前需要开启定位权限,代码如下:
public void checkPermissions() { // 检查权限状态 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { boolean locationPermission = PermissionUtils.hasPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION); boolean accessPermission = PermissionUtils.hasPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION); if (!locationPermission || !accessPermission) { // 有一个或多个权限未授予,需要申请权限 PermissionUtils.requestPermission(BluetoothPageActivity.this, new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, }, 1001); } else { // 定位权限已授予,初始化蓝牙 initBle(); } } else { // 对于 Android 版本低于 M,直接初始化蓝牙 initBle(); }}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001) { // 处理定位权限请求结果 if (PermissionUtils.verifyPermissions(grantResults)) { // 定位权限已授予,初始化蓝牙 initBle(); } else { // 用户拒绝了权限请求,可以进行相应的处理 } }}private void initBle() { // 在这里进行初始化蓝牙的操作 // ...} 记得在 initBle() 方法中添加蓝牙初始化的逻辑,确保在权限已授予的情况下顺利进行蓝牙搜索设备的操作。
三、兼容性优化
3.1 检查蓝牙硬件支持
在动态请求蓝牙权限之前,最好先检查设备是否支持蓝牙硬件。这可以通过以下方式实现:
private boolean isBluetoothHardwareSupported() { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);} 3.2 处理蓝牙不可用的情况
如果设备不支持蓝牙,最好显示一个提示对话框,而不是尝试启用蓝牙。
private void showBluetoothNotSupportedDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("该设备不支持蓝牙功能") .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // 关闭应用或其他操作 } }); builder.create().show();} 3.3 显示权限被拒绝的提示
如果用户拒绝了蓝牙权限,你可以显示一个对话框,提醒用户为什么需要这个权限,并引导用户到应用程序设置中手动授予权限。
private void showPermissionDeniedDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("蓝牙权限被拒绝,请在应用设置中手动授予权限") .setPositiveButton("去设置", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { openAppSettings(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // 关闭应用或其他操作 } }); builder.create().show();}// 打开应用程序设置页面private void openAppSettings() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())); startActivity(intent);} 总结
通过上述优化,你可以更好地适配各种 Android 设备,并以用户友好的方式处理蓝牙权限的申请。这个指南提供了一个完整的解决方案,确保在不同的设备上成功使用蓝牙功能,提升应用的用户体验。
下一篇:服务器怎么关闭大小写?