Google Maps API显示当前位置异常及权限替代方案咨询
问题解决方案
1. 用registerForActivityResult替代Fragment中废弃的onRequestPermissionsResult
在Fragment中,直接通过registerForActivityResult声明权限请求启动器,替代原有的onRequestPermissionsResult方法,所有权限处理逻辑都在启动器回调中完成:
步骤1:声明权限请求Launcher
在HomeFragment类中添加成员变量:
import androidx.activity.result.contract.ActivityResultContracts import android.Manifest import android.widget.Toast import androidx.core.content.ContextCompat private val requestLocationPermissionLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted: Boolean -> if (isGranted) { // 权限授予成功,执行地图定位初始化 setupMapLocation() } else { // 权限被拒绝,提示用户 Toast.makeText(requireContext(), "需要位置权限才能显示当前位置", Toast.LENGTH_SHORT).show() } }
步骤2:发起权限请求
在需要检查权限的地方(比如地图初始化后)调用:
fun checkLocationPermission() { if (ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { // 未授权,发起请求 requestLocationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION) } else { // 已授权,直接初始化定位 setupMapLocation() } }
这样就完全替代了onRequestPermissionsResult的逻辑,无需再重写该废弃方法。
2. 修复Google Maps显示默认位置(山景城)而非德国当前位置的问题
已授权位置权限但显示默认位置,通常是因为没有主动获取并移动相机到当前位置,或者设备定位服务未启用。以下是具体修复步骤:
步骤1:添加必要依赖与权限
确保build.gradle(Module级)中添加了Fused Location Provider依赖:
dependencies { implementation 'com.google.android.gms:play-services-location:21.0.1' implementation 'com.google.android.gms:play-services-maps:18.1.0' }
在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-feature android:name="android.hardware.location.gps" android:required="false" /> <!-- 确保已配置Google Maps API密钥 --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="你的API密钥"/>
步骤2:实现定位并移动相机到当前位置
在HomeFragment中通过FusedLocationProviderClient获取当前位置,并控制地图相机移动:
import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationServices import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.LatLng import android.os.Looper private lateinit var googleMap: GoogleMap private lateinit var fusedLocationClient: FusedLocationProviderClient override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) // 初始化地图 val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) } override fun onMapReady(map: GoogleMap) { googleMap = map // 启用我的位置图层和按钮 googleMap.isMyLocationEnabled = true googleMap.uiSettings.isMyLocationButtonEnabled = true // 检查权限并获取当前位置 checkLocationPermission() } private fun setupMapLocation() { if (ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { // 获取最后已知位置 fusedLocationClient.lastLocation.addOnSuccessListener { location -> location?.let { val currentLatLng = LatLng(it.latitude, it.longitude) // 移动相机到当前位置,缩放级别15 googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f)) } ?: run { // 如果lastLocation为空,请求实时位置更新 val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_HIGH_ACCURACY interval = 10000 fastestInterval = 5000 } fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() ) } } } } // 位置更新回调 private val locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) val location = locationResult.lastLocation location?.let { val currentLatLng = LatLng(it.latitude, it.longitude) googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f)) // 获取到位置后停止更新 fusedLocationClient.removeLocationUpdates(this) } } }
额外检查点
- 真机:确保设备开启了高精度定位模式,并允许应用访问位置。
- 模拟器:在模拟器设置中添加德国的模拟坐标(比如柏林:52.5200° N, 13.4050° E),或者使用模拟器的位置模拟功能。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

