You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin地图应用请求位置权限后闪退,模拟器显示空白屏求助

问题分析与解决方案

核心问题排查

你的应用出现物理设备闪退、模拟器空白屏的问题,主要由以下几个原因导致:

  1. 无效的Google Maps API Key:代码中硬编码的"API_KEY_HERE"未替换为有效密钥,导致Maps SDK初始化失败,引发崩溃或空白屏。
  2. 权限处理逻辑错误:在Composable函数中调用权限请求方法,导致重复触发请求,且异步权限结果的响应逻辑存在疏漏。
  3. 空指针异常风险:使用!!非空断言访问可能为null的lastKnownLocation,在设备无缓存位置时直接崩溃。
  4. 异步操作未正确封装:位置请求直接写在Composable顶层,导致每次重组都重复执行,引发不必要的资源消耗和异常。

分步解决方案

1. 配置有效Google Maps API Key

  • 替换代码中Places.initialize(applicationContext, "API_KEY_HERE")的"API_KEY_HERE"为你的有效Google Maps API Key,确保该密钥已启用Maps SDK for Android服务,且绑定了正确的应用包名和SHA-1指纹(物理设备必须配置SHA-1)。
  • 在AndroidManifest.xml中添加Maps SDK的元数据配置:
<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="你的有效API_KEY"/>

2. 修复权限处理逻辑

将权限请求从Composable代码中移出,放在Activity的onCreate方法中执行,避免重复触发:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Places.initialize(applicationContext, "你的API_KEY")
    getLocationPermission() // 移到这里执行
    
    setContent {
        MapsAlphaProjectTheme {
            if (locationPermissionGranted.value) {
                MapScreen()
            } else {
                Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                    Text("需要位置权限才能使用地图")
                }
            }
        }
    }
}

3. 重构MapScreen的位置请求逻辑

使用LaunchedEffect封装异步位置请求,避免重复执行;移除强制类型转换,处理空值情况:

@Composable
fun MapScreen() {
    val context = LocalContext.current
    val fusedLocationProviderClient = remember {
        LocationServices.getFusedLocationProviderClient(context)
    }

    var deviceLatLng by remember {
        mutableStateOf(LatLng(0.0, 0.0))
    }

    val cameraPositionState = rememberCameraPositionState {
        position = CameraPosition.fromLatLngZoom(deviceLatLng, 18f)
    }

    // 用LaunchedEffect执行一次性异步操作
    LaunchedEffect(Unit) {
        fusedLocationProviderClient.lastLocation.addOnCompleteListener { task ->
            if (task.isSuccessful) {
                task.result?.let { location ->
                    deviceLatLng = LatLng(location.latitude, location.longitude)
                    cameraPositionState.position = CameraPosition.fromLatLngZoom(deviceLatLng, 18f)
                } ?: run {
                    Log.d(TAG, "无缓存位置,使用默认坐标")
                    // 可在这里设置默认位置,比如:
                    // deviceLatLng = LatLng(39.9042, 116.4074) // 北京坐标
                }
            } else {
                Log.e(TAG, "获取位置失败", task.exception)
            }
        }
    }

    GoogleMap(
        modifier = Modifier.fillMaxSize(), // 必须添加fillMaxSize,否则地图不可见
        cameraPositionState = cameraPositionState
    ) {
        MarkerInfoWindowContent(
            state = MarkerState(position = deviceLatLng)
        ) { marker ->
            Text(marker.title ?: "当前位置", color = Color.Red)
        }
    }
}

4. 补充清单文件权限

确保AndroidManifest.xml中添加了必要的位置权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 可选:如果不需要强制GPS硬件,添加以下声明 -->
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>

额外注意事项

  • 物理设备测试时,确保已开启位置服务,且应用已获得位置权限。
  • 若模拟器仍显示空白屏,检查模拟器是否已配置Google Play服务,且API Key允许模拟器的SHA-1(或使用调试SHA-1)。
  • 移除未使用的Places初始化代码(如果你的应用不需要Places服务),避免不必要的API Key校验。

内容的提问来源于stack exchange,提问作者Adit Ramdas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:56