Android 12蓝牙报java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission

发布时间 2023-04-06 10:33:40作者: xiaowang_lj

报错如下:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.studay.base.study, PID: 16798
    java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission for AttributionSource { uid = 10392, packageName = com.studay.base.study, attributionTag = null, token = android.os.BinderProxy@3a97bdd, next = null }: enable
        at android.os.Parcel.createExceptionOrNull(Parcel.java:2438)
        at android.os.Parcel.createException(Parcel.java:2422)
        at android.os.Parcel.readException(Parcel.java:2405)
        at android.os.Parcel.readException(Parcel.java:2347)
        at android.bluetooth.IBluetoothManager$Stub$Proxy.enable(IBluetoothManager.java:987)
        at android.bluetooth.BluetoothAdapter.enable(BluetoothAdapter.java:2219)
        at com.studay.base.study.bluetooth.BluetoothFragment$1.onClick(BluetoothFragment.java:85)
        at android.view.View.performClick(View.java:7792)
        at android.widget.TextView.performClick(TextView.java:16112)
        at android.view.View.performClickInternal(View.java:7769)
        at android.view.View.access$3800(View.java:910)
        at android.view.View$PerformClick.run(View.java:30218)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8751)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
     Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.server.BluetoothManagerService.checkPermissionForDataDelivery(BluetoothManagerService.java:5034)
        at com.android.server.BluetoothManagerService.checkConnectPermissionForDataDelivery(BluetoothManagerService.java:5052)
        at com.android.server.BluetoothManagerService.checkBluetoothPermissions(BluetoothManagerService.java:1506)
        at com.android.server.BluetoothManagerService.enable(BluetoothManagerService.java:1787)
        at android.bluetooth.IBluetoothManager$Stub.onTransact(IBluetoothManager.java:441)

 

  <!-- Required to be able to connect to paired Bluetooth devices.
         <p>Protection level: dangerous -->
    <permission android:name="android.permission.BLUETOOTH_CONNECT"
        android:permissionGroup="android.permission-group.UNDEFINED"
        android:description="@string/permdesc_bluetooth_connect"
        android:label="@string/permlab_bluetooth_connect"
        android:protectionLevel="dangerous" />

 

近期遇到一个问题,之前发布的APP连接蓝牙都是正常的,现在有人反映连不上了。经过测试发现:android 12 和 harmonyOS 3.0.0 都会有这个问题,而之前的版本就不会有这个。

        经过网上一番查找,原来是因为最近Google发布的Android 12,新引入了 BLUETOOTH_SCAN、BLUETOOTH_CONNECT、BLUETOOTH_ADVERTISE 三个权限。

        从Android 12开始,过去的蓝牙权限被拆分成了3个新的权限,并且全都是运行时权限(需要动态申请):

  • BLUETOOTH_SCAN 用于使用蓝牙扫描附件其他的蓝牙设备
  • BLUETOOTH_ADVERTISE 用于允许当前的设备被其他的蓝牙设备所发现
  • BLUETOOTH_CONNECT 用于连接之前已经配对过的蓝牙设备

        这3个权限都是从Android 12系统才开始有的,所以为了能够兼容过去的老版本,建议在AndroidManifest.xml中这样声明:

 
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
 
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
 
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
 
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
 
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

        新增的3个蓝牙权限都是运行时权限,因此只在AndroidManifest.xml中声明是没有用的,还要在代码中动态申请权限才行。必须先在应用中用户明确批准使用,然后才能查找蓝牙设备、使某个设备可被其他设备检测到,或者与已配对的蓝牙设备通信。

        具体的申请方法如下:首先要判断当前的系统版本,只有当Android 12及以上系统时,才应该去请求新增的蓝牙权限。(PS:3个权限都属于同一个权限组,因此理论上只要申请一个权限,另外2个也就自动授权了。)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            String[] permission = checkSelfPermissionArray(this, new String[]{
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.BLUETOOTH_ADVERTISE,
                    Manifest.permission.BLUETOOTH_CONNECT});
            if (permission.length > 0) {
                ActivityCompat.requestPermissions(this, permission, 102);
            }
        }

注意:

之前的Android系统中有一个很奇怪的现象,当我们在应用中使用蓝牙扫描附件设备的时候,需要申请地理位置权限。蓝牙权限并不是运行时权限,但地理位置权限却是。

(299条消息) Android连接蓝牙设备问题(android.permission.BLUETOOTH)_老杜_d的博客-CSDN博客

(299条消息) android设置打开蓝牙时报错:java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission_YaXinShi的博客-CSDN博客