Android 12 个新的蓝牙权限

Android 12 New Bluetooth Permissions

蓝牙是我们应用程序的主要依赖项。因此,我们已经尝试实施新的 Android 12 项蓝牙权限。我们唯一的资源是 Android developers New Bluetooth permissions in Android 12。只是说添加权限

"android.permission.BLUETOOTH_CONNECT"

"android.permission.BLUETOOTH_SCAN"

我添加并获得了这两个位置的运行时权限(通常为 12 之前))。
我的代码库中没有其他更改。应该?我不知道。所以,问题是我的应用找不到 BLE 设备。我找不到原因。

您有什么建议或资源吗?

If you want your app to initiate device discovery or manipulate Bluetooth settings, you must declare the BLUETOOTH_ADMIN permission in addition to the BLUETOOTH permission. Most apps need this permission solely for the ability to discover local Bluetooth devices. Don't use the other abilities granted by this permission unless the app is a "power manager" that modifies Bluetooth settings upon user request. Declare the Bluetooth permission(s) in your app manifest file

developer android 我们看到你必须添加

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

在你的清单文件中,但你没有添加它来发现其他设备我认为这是你问题的来源

我不确定他们是否宣布了任何关于蓝牙更改的信息,但如果没有其他帮助,他们最近介绍了这个,这可能对您的用例有所帮助,除非您做更复杂的事情。

https://developer.android.com/guide/topics/connectivity/companion-device-pairing#kotlin

在较新的版本中,如果这能满足您的所有需求,您也不再需要位置权限。

关于示例:您可以不包括这两行:

    .setNamePattern(Pattern.compile("My device"))
    .addServiceUuid(ParcelUuid(UUID(0x123abcL, -1L)), null)

我用它来搜索设备没有任何问题,连接工作类似

我刚刚添加到清单中:

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

然后我像其他人一样从 Main Activity 请求这些权限。 为了请求许可,我正在使用库

implementation 'pub.devrel:easypermissions:3.0.0'

那你就可以调用这个函数了

public static final String[] BLUETOOTH_PERMISSIONS_S = { Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT} ;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
     if (!EasyPermissions.hasPermissions(this, BLUETOOTH_PERMISSIONS_S)) {
                EasyPermissions.requestPermissions(this, message, yourRequestCode,BLUETOOTH_PERMISSIONS_S);
            }
        }

并覆盖 onRequestPermissionResult

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

JETPACK COMPOSE 更新

如果您使用的是 Jetpack Compose,您可以这样处理:

在 rememberMultiplePermissionState 函数中创建您的权限列表

 rememberMultiplePermissionsState(
            permissions = listOf(
                Manifest.permission.BLUETOOTH_CONNECT,
                Manifest.permission.BLUETOOTH_SCAN
            )
        )

然后观察生命周期事件并在恢复启动权限请求时

    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(key1 = lifecycleOwner,
        effect = {
            val observer = LifecycleEventObserver { _, event ->
                if(event == Lifecycle.Event.ON_START) {
                    permissionsState.launchMultiplePermissionRequest()
                }
            }
            lifecycleOwner.lifecycle.addObserver(observer)

            onDispose {
                lifecycleOwner.lifecycle.removeObserver(observer)
            }
        })

观察权限状态

permissionsState.permissions.forEach { permissionState ->
            when(permissionState.permission) {
                Manifest.permission.ACCESS_FINE_LOCATION -> {
                    when {
                        permissionState.hasPermission -> {}
                    }
                }
            }
        }
    }

这是一个平台错误。 Google 修复了新 Android 12 Beta 版本中的错误。

100% 工作解决方案:不需要任何第 3 方插件

清单代码:

   <!--BLUETOOTH PERMISSION-->
    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- Needed only if your app looks for Bluetooth devices.
             If your app doesn't use Bluetooth scan results to derive physical
             location information, you can strongly assert that your app
             doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <!-- Needed only if your app makes the device discoverable to Bluetooth
      devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <!-- Needed only if your app communicates with already-paired Bluetooth
           devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <!--bibo01 : hardware option-->
    <uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>

Kotlin 代码:

 //check android12+
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            requestMultiplePermissions.launch(arrayOf(
                                Manifest.permission.BLUETOOTH_SCAN,
                                Manifest.permission.BLUETOOTH_CONNECT))
                        }
                        else{
                            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
                            requestBluetooth.launch(enableBtIntent)
                        }
....................................................

private var requestBluetooth = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == RESULT_OK) {
                    //granted
                }else{
                    //deny
                }
 }

private val requestMultiplePermissions =
                registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
                    permissions.entries.forEach {
                        Log.d("test006", "${it.key} = ${it.value}")
                    }
}

阅读更多: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions

这对我有用,

在清单中,添加以下权限:

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

然后,在执行蓝牙功能之前,检查权限:

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) 
                {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) 
                    {
                        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 2);
                        return;
                    }
                }

举个例子,

if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, 2);
                            return;
                        }
                    }
                    mBTSocket.connect();