Reputation: 309
I am designing an app in Android Studio. It scans for BLE (Bluettoth Low Energy) devices.
As soon as I try to scan I get the following popup message:
Location permission required
Starting from Android M (6.0), the system requires apps to be granted location access in order to scan for BLE devices.
There is no OK button or anything.
Is there a way to add (Kotlin) code, before scanning, to
(a) check if Bluetooth Location Permission has already been granted by the user for this app, and
(b) if not yet granted, to programmatically launch/open the settings page for the user
Thanks in advance
Garrett
EXTRA INFORMATION / QUESTION ADDED......
Thank you user18309290 for your response.
I went through the documentation, and together with other examples I found, I cobbled together the following code, which works and maybe doesn’t work.
Behaviour:
The very first time the app is launched, the Android OS prompts the user to allow access to the device's location:
Allow YourApp to access this device's location?
While using the app
Only this time
Don't allow
So, I selected "Don't allow", so that I could test my code
From then on, the Alert Dialog pops up, notifying the user that the device requirs location access. When the user selects "OK", the relevant permission(s) are requested. However, the result of the requestPermissions() call is always PERMISSION_DENIED.
Now, what I don’t know is if this is the correct / expected behaviour of my code, or not.
When requestPermissions() is called, should this prompt the Android OS to display the location options to the user (While using the app | Only this time | Don't allow) or does this call just reflect the current setting?
Is there a separate call my code needs to make to actually get the OS to launch the location setting option?
I have detailed my code below.
<!-- Request legacy Bluetooth permissions on older devices. -->
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- 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" />
<!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
In MainActivity.kt:
private fun requestLocationPermission() {
if (isLocationPermissionGranted) {
return
}
runOnUiThread {
val builder = AlertDialog.Builder(this, R.style.AlertDialogCustom)
builder.setMessage("Starting from Android M (6.0), the system requires apps to be granted " +
"location access in order to scan for BLE devices.\n" +
"Open Bluetooth settings for this app now?")
.setPositiveButton(android.R.string.ok,
DialogInterface.OnClickListener { dialog, id ->
requestBlePermissions(this, LOCATION_PERMISSION_REQUEST_CODE)
})
.setNegativeButton(android.R.string.cancel,
DialogInterface.OnClickListener { dialog, id ->
// do something
})
.setTitle("Location permission required")
// Create the AlertDialog
val alertDialog: AlertDialog = builder.create()
// Set other dialog properties
alertDialog.setCancelable(false)
alertDialog.show()
}
}
fun requestBlePermissions(activity: Activity?, requestCode: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
ActivityCompat.requestPermissions(
activity!!,
ANDROID_12_BLE_PERMISSIONS,
requestCode
)
} else {
ActivityCompat.requestPermissions(
activity!!,
BLE_PERMISSIONS,
requestCode
)
}
}
private val BLE_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
private val ANDROID_12_BLE_PERMISSIONS = arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
LOCATION_PERMISSION_REQUEST_CODE -> {
if (grantResults.firstOrNull() == PackageManager.PERMISSION_DENIED) {
requestLocationPermission()
} else {
startBleScan()
}
}
}
}
Upvotes: 1
Views: 1612
Reputation: 8340
Here are instructions on how to request location permission: Request location access at runtime.
Note that from Android 12 or higher permissions for BLE usage has changed. Location permission is replaced with BLUETOOTH_SCAN
. See details Bluetooth permissions.
Upvotes: 2