Android 12 蓝牙权限

7

我正在尝试使用BLE连接设备,但在Android 12上出现了错误。我尝试了很多不同的方法,但没有找到任何解决方案。如何请求蓝牙权限?

AndroidManifest.xml

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <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" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

 <uses-feature android:name="android.hardware.bluetooth_le"
        android:required="true" />

 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

权限请求代码

private static final String[] BLE_PERMISSIONS = new String[]{
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
    };
    
private static final String[] ANDROID_12_BLE_PERMISSIONS = new String[]{
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.BLUETOOTH_CONNECT,
            Manifest.permission.ACCESS_FINE_LOCATION,
    };

public static void requestBlePermissions(Activity activity, int requestCode) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
        ActivityCompat.requestPermissions(activity, ANDROID_12_BLE_PERMISSIONS, requestCode);
    else
        ActivityCompat.requestPermissions(activity, BLE_PERMISSIONS, requestCode);
}

错误信息:
Fatal Exception: java.lang.SecurityException
Need android.permission.BLUETOOTH_CONNECT permission for android.content.AttributionSource@3d290817: GattService registerClient

1
请问您能否[编辑]您的问题并将完整的错误信息添加到其中? - Michael Kotzjan
当请求权限时,难道不应该传递一个包含所有权限的数组吗? - Emil
你能检查一下你是否已经拥有权限吗?这里有一个代码示例。 运行时是否会弹出请求权限的窗口? - fabik111
@Enes 我建议您覆盖onRequestPermissionsResult函数,这样您就能够获取请求权限操作的结果。 - fabik111
@Enes 我让你重写那个函数,希望结果值能帮助你调试。顺便提一下,根据谷歌:BLUETOOTH_ADVERTISE、BLUETOOTH_CONNECT和BLUETOOTH_SCAN 权限是运行时权限。因此,在您的应用程序中寻找蓝牙设备、[...]或与已配对的蓝牙设备通信之前,必须明确请求用户批准。 问题可能在于您如何进行权限请求,请检查我的答案如何操作。它也适用于API 31。 - fabik111
显示剩余2条评论
3个回答

12

看起来这应该能够工作,但如果您实际上不需要位置权限,我建议采用以下方法。

<uses-permission
    android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation"
    tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<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.ACCESS_COARSE_LOCATION"
    android:maxSdkVersion="30" />
<uses-permission
    android:name="android.permission.ACCESS_FINE_LOCATION"
    android:maxSdkVersion="30" />

请求获得许可

private static final String[] BLE_PERMISSIONS = new String[]{
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
};

@RequiresApi(api = Build.VERSION_CODES.S)
private static final String[] ANDROID_12_BLE_PERMISSIONS = new String[]{
        Manifest.permission.BLUETOOTH_SCAN,
        Manifest.permission.BLUETOOTH_CONNECT
};

1
这样的答案包含依赖于版本的代码,但没有解释。例如:tools:targetApi="s",android:maxSdkVersion="30",很快就会过时。随着版本的更新,很难猜测版本号是否仍然相关,应该更改以匹配新版本,删除还是其他操作。 - Graeme Gill
答案必然与版本有关,因为OP正在询问Android 12(S),它是API级别31。答案不会过时,因为API版本30及以下始终需要这些权限。最好不要瞎猜或盲目从SO复制代码而不进行验证。 - gaggleweed

6

我也是按照 Android 文档中的代码进行操作的。如果你在 Android 12 设备上进行测试和运行,请移除最大 SDK 版本 30。

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

除此之外,你的代码很好。

并且您可以使用同样的代码请求运行时蓝牙权限。

private static final String[] BLE_PERMISSIONS = new String[]{
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
    };
    
private static final String[] ANDROID_12_BLE_PERMISSIONS = new String[]{
            Manifest.permission.BLUETOOTH_SCAN,
            Manifest.permission.BLUETOOTH_CONNECT,
            Manifest.permission.ACCESS_FINE_LOCATION,
    };

public static void requestBlePermissions(Activity activity, int requestCode) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
        ActivityCompat.requestPermissions(activity, ANDROID_12_BLE_PERMISSIONS, requestCode);
    else
        ActivityCompat.requestPermissions(activity, BLE_PERMISSIONS, requestCode);
}

为什么要使用ActivityCompat而不是androidx - IgorGanapolsky

-4

目标 SDK 版本修复为 30。(旧版本为 31)

我修复了一个错误!


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
“Fix”太难懂了,不知道它应用于什么。 - Graeme Gill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接