Bluetooth is the main dependency of our app. So, We already try to implement new Android 12 Bluetooth permissions. Our only resource is Android developers New Bluetooth permissions in Android 12. There is just saying add permissions
"android.permission.BLUETOOTH_CONNECT"
"android.permission.BLUETOOTH_SCAN"
I add and I got runtime permissions for both and of course location(usual as pre 12)).
There is no other change in my codebase. Should be? I don't know. So, the problem is my app can't find the BLE device. I couldn't find the reason.
Do you have any suggestions or resources?
If your app looks for Bluetooth devices, such as BLE peripherals, declare the BLUETOOTH_SCAN permission. If your app makes the current device discoverable to other Bluetooth devices, declare the BLUETOOTH_ADVERTISE permission.
Your app needs this permission because a Bluetooth scan can be used to gather information about the location of the user. This information may come from the user's own devices, as well as Bluetooth beacons in use at locations such as shops and transit facilities.”
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.
So even if an app just scans for Bluetooth devices and doesn’t utilize GPS or other tracking technologies, it still needed the same Location permission nonetheless. However, this led to unforeseen consequences when due to misunderstandings from users.
Needed only if your app uses Bluetooth scan results to derive physical location. --> ... If your app doesn't use Bluetooth scan results to derive physical location, you can make a strong assertion that your app never uses the Bluetooth permissions to derive physical location. To do so, complete the following steps:
Basically, before Android 12, the ability to scan for nearby Bluetooth or Wi-Fi devices were tied to Android’s broader “location” permission. The reason this was the case makes sense: You can definitely track a device by inferring what Bluetooth devices or Wi-Fi networks are nearby or are currently connected.
100% working solution : no need any 3rd party plugin
manifest code:
<!--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 code: //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}")
}
}
Read more: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
This worked for me,
In the manifest, add the following 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" />
Then, before executing a Bluetooth function, check the permission:
//--------------------------Java--------------------------
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;
}
}
//--------------------------Kotlin--------------------------
if (ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
ActivityCompat.requestPermissions(this@MainActivity, arrayOf(Manifest.permission.BLUETOOTH_CONNECT), 2)
return
}
}
For an example,
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();
I just added to the manifest:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
and then I requested those permissions from Main Activity as any other. For requesting permission I am using library
implementation 'pub.devrel:easypermissions:3.0.0'
then you can just call this function
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);
}
}
and override onRequestPermissionResult
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
UPDATE FOR JETPACK COMPOSE
If you are using jetpack compose you can handle it like this:
Create a list of your permissions inside of rememberMultiplePermissionState function
rememberMultiplePermissionsState(
permissions = listOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN
)
)
Then observe a lifecycle events and on resume launch permission request
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)
}
})
Observe the permission state
permissionsState.permissions.forEach { permissionState ->
when(permissionState.permission) {
Manifest.permission.ACCESS_FINE_LOCATION -> {
when {
permissionState.hasPermission -> {}
}
}
}
}
}
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
from developer android we see you have to add
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
in your manifest file but you did not add it to discover other devices i think this is the resource of your problem
This was a platform bug. Google fixed the bug in the new Android 12 Beta version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With