如何在Kotlin中使用FusedLocationClient获取Google Maps当前位置
解决FusedLocationProviderClient无法获取当前位置的问题
你用lastLocation拿不到当前位置,核心原因是这个方法只会返回设备最近缓存的位置信息——如果设备近期没有触发过定位操作,它就会返回null,并不会主动请求新的定位数据。
下面给你两种可行的解决方案:
方案一:单次主动获取当前位置(适合只需要一次定位的场景)
使用getCurrentLocation方法,它会主动向定位服务请求一次当前位置,替代原来的lastLocation:
private fun getCurrentLocationUser() { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode) return } // 配置定位请求参数:高精度、超时时间等 val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY timeoutMillis = 10000 // 10秒内没拿到位置就超时 maxWaitTimeMillis = 15000 // 最长等待定位结果的时间 } // 主动获取当前位置 fusedLocationProviderClient.getCurrentLocation(locationRequest, null) .addOnSuccessListener { location -> if (location != null) { currentLocation = location Toast.makeText(applicationContext, "${currentLocation.latitude}, ${currentLocation.longitude}", Toast.LENGTH_SHORT).show() val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } else { Toast.makeText(applicationContext, "无法获取当前位置,请检查定位设置", Toast.LENGTH_SHORT).show() } } .addOnFailureListener { e -> Toast.makeText(applicationContext, "定位失败:${e.message}", Toast.LENGTH_SHORT).show() } }
方案二:持续获取位置更新(适合需要实时跟踪位置的场景)
如果你的需求是实时更新位置,比如导航类应用,可以用requestLocationUpdates持续监听位置变化,记得在不需要的时候停止监听:
private lateinit var locationCallback: LocationCallback private fun startLocationUpdates() { if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), permissionCode) return } val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY intervalMillis = 5000 // 每5秒更新一次位置 fastestIntervalMillis = 2000 // 最快更新间隔(避免频繁更新) } locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) // 获取最新位置并更新地图 locationResult.lastLocation?.let { location -> currentLocation = location updateMapLocation() } } } // 开始监听位置更新 fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) } // 更新地图上的位置标记 private fun updateMapLocation() { val latLng = LatLng(currentLocation.latitude, currentLocation.longitude) val markerOptions = MarkerOptions().position(latLng).title("当前位置") mMap?.clear() // 清除旧标记 mMap?.addMarker(markerOptions) mMap?.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15f)) } // Activity销毁时停止位置监听,避免内存泄漏 override fun onDestroy() { super.onDestroy() fusedLocationProviderClient.removeLocationUpdates(locationCallback) }
额外要注意的点
- 确保
AndroidManifest.xml中已经添加了必要的权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Android 12及以上版本,如需后台定位还需添加: --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
- 测试时尽量在室外环境,室内高精度定位可能会失败。
内容的提问来源于stack exchange,提问作者Arpit Gupta
相关产品推荐
相关产品推荐

