Issue
I am testing android permissions for both camera and location. Surprisingly to me, I learned that when I give access to fine location, system also gives permission to coarse location. Is this normal? I first checked with Toasts to see the granted accesses. When I give access to coarse only, it shows that fine location permission is denied, which is normal. But when I give access to fine address, it also gives permission to coarse location. Is this normal?
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private var cameraResultLauncher: ActivityResultLauncher<String> =
registerForActivityResult(
ActivityResultContracts.RequestPermission()){
isGranted ->
if (isGranted){
Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show()
}else{
Toast.makeText(this, "Permission denied", Toast.LENGTH_LONG).show()
}
}
//This time we create the Activity result launcher of type Array<String>
private var cameraAndLocationResultLauncher: ActivityResultLauncher<Array<String>> =
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()){
permissions ->
/**
Here it returns a Map of permission name as key with boolean as value
Loop through the map to get the value we need which is the boolean
value
*/
permissions.entries.forEach{
val permissionName = it.key
val isGranted = it.value
println(permissionName)
println(isGranted)
if (isGranted){
if (permissionName == Manifest.permission.ACCESS_FINE_LOCATION){
Toast.makeText(this, "Permission granted for fine location", Toast.LENGTH_LONG).show()
}else if(permissionName == Manifest.permission.ACCESS_COARSE_LOCATION){
Toast.makeText(this, "Permission granted for coarse location", Toast.LENGTH_LONG).show()
}else{
Toast.makeText(this, "Permission granted for Camera", Toast.LENGTH_LONG).show()
}
}else{
if (permissionName == Manifest.permission.ACCESS_FINE_LOCATION){
Toast.makeText(this, "Permission denied for fine location", Toast.LENGTH_LONG).show()
}else if(permissionName == Manifest.permission.ACCESS_COARSE_LOCATION){
Toast.makeText(this, "Permission denied for coarse location", Toast.LENGTH_LONG).show()
}else{
Toast.makeText(this, "Permission denied for Camera", Toast.LENGTH_LONG).show()
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val btnCameraPermission: Button = binding.btnCameraPermission
btnCameraPermission.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && shouldShowRequestPermissionRationale(
Manifest.permission.CAMERA)){
showRationaleDialog("Permission Demo requires camera access", "Camera cannot be used because Camera access is denied")
}else{
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
// cameraResultLauncher.launch(Manifest.permission.CAMERA) this for only camera permission
cameraAndLocationResultLauncher.launch(arrayOf(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION))
}
}
}
private fun showRationaleDialog(
title: String,
message: String,
){
val builder: AlertDialog.Builder = AlertDialog.Builder(this)
builder.setTitle(title)
.setMessage(message)
.setPositiveButton("Cancel"){
dialog, _-> dialog.dismiss()
}
builder.create().show()
}
}
I/System.out: android.permission.ACCESS_FINE_LOCATION
I/System.out: true
I/System.out: android.permission.ACCESS_COARSE_LOCATION
I/System.out: true
Solution
Is this normal?
Yes. Most permissions are not set up this way, but this pair is. After all, if you can measure location within a few dozen meters (ACCESS_FINE_LOCATION
), then by definition you can measure location within a much larger radius (ACCESS_COARSE_LOCATION
).
Answered By - CommonsWare
Answer Checked By - Gilberto Lyons (JavaFixing Admin)