Gradle迁移至Kotlin DSL后Google Maps API权限异常求助
问题分析与解决方案
这个错误和Gradle Kotlin DSL完全无关——权限机制是Android系统的核心逻辑,和构建脚本的语言没有关联。你遇到的问题本质是:Google Maps的setMyLocationEnabled()方法会主动检查权限状态,即使你已经在Manifest中声明权限、且能通过其他API获取位置,只要调用该方法时权限未被用户授予,就会触发这个错误。
核心原因
Android 6.0(API 23)及以上版本中,ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION属于危险权限,仅在Manifest中声明是不够的,必须在运行时向用户申请并获得授权。你提到能正常定位,大概率是通过FusedLocationProviderClient等定位API获取位置,但这些API的权限检查逻辑和Google Maps的setMyLocationEnabled()是分开的——后者会强制校验权限状态。
解决方案
在调用setMyLocationEnabled(true)之前,必须确保已获取至少一个位置权限。以下是标准实现方式:
1. 使用Activity Result API(推荐,适配新版Android)
import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import androidx.activity.result.contract.ActivityResultContracts class MainActivity : AppCompatActivity(), OnMapReadyCallback { private var googleMap: GoogleMap? = null private val LOCATION_PERMISSIONS = arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ) // 注册权限请求回调 private val requestPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions() ) { permissions -> val hasFinePermission = permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false val hasCoarsePermission = permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false if (hasFinePermission || hasCoarsePermission) { // 权限授予成功,开启我的位置 googleMap?.isMyLocationEnabled = true } else { // 权限被拒绝,提示用户 } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } override fun onMapReady(map: GoogleMap) { googleMap = map checkAndRequestLocationPermissions() } private fun checkAndRequestLocationPermissions() { val hasFinePermission = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED val hasCoarsePermission = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED if (hasFinePermission || hasCoarsePermission) { googleMap?.isMyLocationEnabled = true } else { // 申请权限 requestPermissionLauncher.launch(LOCATION_PERMISSIONS) } } }
2. 旧版权限回调方式(兼容API < 33)
如果需要兼容更老的系统版本,可以使用onRequestPermissionsResult:
private val LOCATION_PERMISSION_REQUEST_CODE = 1001 private fun checkAndRequestLocationPermissions() { val hasFinePermission = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED val hasCoarsePermission = ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_COARSE_LOCATION ) == PackageManager.PERMISSION_GRANTED if (hasFinePermission || hasCoarsePermission) { googleMap?.isMyLocationEnabled = true } else { requestPermissions(LOCATION_PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE) } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { val hasFine = grantResults.getOrNull(0) == PackageManager.PERMISSION_GRANTED val hasCoarse = grantResults.getOrNull(1) == PackageManager.PERMISSION_GRANTED if (hasFine || hasCoarse) { googleMap?.isMyLocationEnabled = true } } }
额外注意事项
- 确保在
onMapReady回调之后再处理权限逻辑,避免googleMap实例为空。 - 如果用户拒绝权限,可以在回调中引导用户到应用设置页面开启权限。
- 你的Manifest配置是正确的,不需要修改。
内容的提问来源于stack exchange,提问作者Kafka
相关产品推荐
相关产品推荐

