Android地图onMapReady申请权限报错 如何正确设置mMap.isMyLocationEnabled
问题根因
你遇到的两个报错本质是两个API的调用时机约束冲突:
registerForActivityResult要求必须在Activity生命周期进入STARTED状态之前完成注册,也就是只能在onCreate、onAttach这类更早的生命周期方法里初始化,不能等到onMapReady回调时再注册mMap是lateinit变量,必须等onMapReady回调完成初始化之后才能调用它的属性和方法
修复方案
你需要把权限注册逻辑和权限申请、结果处理逻辑拆分,不要全塞在同一个函数里,步骤如下:
- 把
requestPermissionLauncher提取成Activity的全局成员变量,在onCreate里完成初始化(只注册,不触发申请) - 在
onMapReady回调里,等mMap初始化完成后,再执行权限检查、权限申请的逻辑 - 权限申请通过的回调里直接调用已经初始化完成的
mMap即可
完整修改后代码示例
// 全局声明权限请求器 private lateinit var requestPermissionLauncher: ActivityResultLauncher<String> // 全局声明地图实例 private lateinit var mMap: GoogleMap override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_maps) // 1. 提前注册权限回调,满足registerForActivityResult的时机要求 requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted: Boolean -> if (isGranted) { Toast.makeText(this,"PERMISSION GRANTED", Toast.LENGTH_LONG).show() // 加初始化判断避免极端场景异常 if (::mMap.isInitialized) { mMap.isMyLocationEnabled = true } } else { Toast.makeText(this,"SHUTTING DOWN", Toast.LENGTH_LONG).show() } } // 初始化地图,触发后续onMapReady回调 val mapFragment = supportFragmentManager .findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } override fun onMapReady(googleMap: GoogleMap) { mMap = googleMap // 2. mMap初始化完成后再执行权限检查和申请 requestLocationPermission() } private fun requestLocationPermission(){ when (PackageManager.PERMISSION_GRANTED) { ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) -> { Toast.makeText(this,"PERMISSION'S ALREADY GRANTED", Toast.LENGTH_LONG).show() mMap.isMyLocationEnabled = true } else -> { requestPermissionLauncher.launch( Manifest.permission.ACCESS_FINE_LOCATION) } } }
额外注意:如果你的应用需要兼容Android 12以上的后台位置权限、或者粗略位置权限的降级场景,可以在权限检查分支里补充对应的逻辑,上述代码已经可以解决你当前遇到的冲突问题。
内容的提问来源于stack exchange,提问作者dltayn
相关产品推荐
相关产品推荐

