Android(Kotlin)地图显示当前位置标记问题:定位始终为空
问题分析与解决方案
一、currentLocation为空的原因及修复
1. 核心问题:lastLocation的局限性
fusedLocationProviderClient.lastLocation仅返回设备最近缓存的位置数据,如果模拟器从未获取过位置、缓存过期,就会返回null——这是你遇到空值的主要原因。
2. 修复方案:主动请求实时位置
替换lastLocation为requestLocationUpdates,主动触发位置获取,确保拿到实时数据:
private const val FINE_PERMISSION_CODE = 1 private lateinit var myMap: GoogleMap private var currentLocation: Location? = null // 改为可空类型,避免初始化崩溃 private lateinit var fusedLocationProviderClient: FusedLocationProviderClient private lateinit var locationRequest: LocationRequest private lateinit var locationCallback: LocationCallback class MapActivity : AppCompatActivity(), OnMapReadyCallback { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_map) fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this) initLocationRequest() getCurrentLocation() } private fun initLocationRequest() { locationRequest = LocationRequest.create().apply { interval = 10000 // 10秒更新一次 fastestInterval = 5000 // 最快5秒更新 priority = LocationRequest.PRIORITY_HIGH_ACCURACY } locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { locationResult.lastLocation?.let { location -> currentLocation = location // 获取到位置后初始化地图 val mapFragment = supportFragmentManager.findFragmentById(R.id.map_fragment) as SupportMapFragment mapFragment.getMapAsync(this@MapActivity) // 可选:拿到位置后停止更新 fusedLocationProviderClient.removeLocationUpdates(this) } ?: run { Log.d("Location", "null location") } } } } private fun getCurrentLocation() { // 先检查系统定位是否开启 if (!isLocationEnabled()) { Toast.makeText(this, "请开启系统定位服务", Toast.LENGTH_SHORT).show() startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) return } // 权限检查逻辑修正:只要缺少任一权限就请求 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), FINE_PERMISSION_CODE) return } // 主动请求位置更新 fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) } private fun isLocationEnabled(): Boolean { val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if(requestCode == FINE_PERMISSION_CODE) { if(grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) { getCurrentLocation() } else { Toast.makeText(this, "位置权限未授予,无法获取定位", Toast.LENGTH_SHORT).show() } } } override fun onMapReady(googleMap: GoogleMap) { myMap = googleMap currentLocation?.let { loc -> val curLoc = LatLng(loc.latitude, loc.longitude) Log.d("Location", "${loc.latitude}, ${loc.longitude}") myMap.addMarker(MarkerOptions().position(curLoc).title("My Location")) myMap.moveCamera(CameraUpdateFactory.newLatLngZoom(curLoc, 12f)) } ?: run { Log.d("Location", "当前位置为空,无法添加标记") } } }
3. 模拟器配套设置
- 确保模拟器开启系统定位服务(设置 → 位置 → 开启)
- 打开模拟器的「Extended Controls」(右上角三个点),在「Location」选项卡中设置模拟坐标(可直接选择城市或手动输入经纬度)
二、关闭定位后权限仍显示已授予的说明
这是正常机制:
- 位置权限是APP访问位置信息的许可,一旦授予,除非用户手动在应用设置中撤销,否则会一直显示已授予
- 系统定位开关是控制整个系统是否提供位置数据,关闭后即使APP有权限,也无法获取到位置数据
- 代码中已添加
isLocationEnabled()检查,会在定位关闭时提示用户跳转到设置开启
内容的提问来源于stack exchange,提问作者Jacob Tang
相关产品推荐
相关产品推荐

