授予ACCESS_FINE_LOCATION后自动获得ACCESS_COARSE_LOCATION权限是否正常?
Android定位权限授予逻辑疑问
测试Android相机与定位权限时发现:授予ACCESS_FINE_LOCATION(精确定位)权限后,系统自动同时授予了ACCESS_COARSE_LOCATION(粗略定位)权限;仅授予粗略定位权限时,精确定位权限显示为拒绝(这符合预期),但反向的自动授予情况是否属于正常现象?
测试代码
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() } } // 创建请求多权限的ActivityResultLauncher private var cameraAndLocationResultLauncher: ActivityResultLauncher<Array<String>> = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions()){ permissions -> /** 返回结果为权限名称为key、布尔值为value的Map 遍历Map获取每个权限的授权状态 */ permissions.entries.forEach{ val permissionName = it.key val isGranted = it.value println(permissionName) println(isGranted) if (isGranted){ when(permissionName) { Manifest.permission.ACCESS_FINE_LOCATION -> Toast.makeText(this, "精确定位权限已授予", Toast.LENGTH_LONG).show() Manifest.permission.ACCESS_COARSE_LOCATION -> Toast.makeText(this, "粗略定位权限已授予", Toast.LENGTH_LONG).show() else -> Toast.makeText(this, "相机权限已授予", Toast.LENGTH_LONG).show() } }else{ when(permissionName) { Manifest.permission.ACCESS_FINE_LOCATION -> Toast.makeText(this, "精确定位权限已拒绝", Toast.LENGTH_LONG).show() Manifest.permission.ACCESS_COARSE_LOCATION -> Toast.makeText(this, "粗略定位权限已拒绝", Toast.LENGTH_LONG).show() else -> Toast.makeText(this, "相机权限已拒绝", 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("权限演示需要相机权限", "无法使用相机,因为相机权限已被拒绝") }else{ // 直接请求权限,结果由注册的ActivityResultCallback接收 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("取消"){ 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
解答
这是完全正常的现象,符合Android权限体系的设计逻辑:
ACCESS_FINE_LOCATION(精确定位)权限的覆盖范围高于ACCESS_COARSE_LOCATION(粗略定位),前者能获取比后者更精准的位置信息,自然涵盖了后者的权限能力。- 当用户授予精确定位权限时,系统会自动判定应用同时拥有粗略定位权限,无需额外单独授权;反之,粗略定位权限不包含精确定位的能力,所以单独授予粗略定位时,精确定位权限仍处于拒绝状态。
这种设计是为了简化权限管理,避免用户重复授予逻辑上存在包含关系的权限,同时保证权限粒度的合理控制。
内容的提问来源于stack exchange,提问作者orhanuckulac
相关产品推荐
相关产品推荐

