Android Studio无法获取定位,调用getLatitude空指针异常如何解决
Android 实时定位空指针问题修复方案
错误原因
你遇到的空指针异常是调用fusedLocationClient.lastLocation时触发,该接口仅返回系统缓存的历史位置,无有效缓存时就会返回null,直接调用getLatitude()方法就会触发空引用异常,且该接口本身就不满足实时定位的需求。
修复步骤
你需要改用requestLocationUpdates主动发起实时定位请求,具体修改如下:
- 新增位置相关API导入
- 初始化定位请求配置与定位结果回调
- 替换原有缓存定位逻辑为主动实时定位
- 补全权限回调逻辑,新增生命周期资源释放避免内存泄漏
完整修改后代码
import android.Manifest import android.content.Context import android.content.pm.PackageManager import android.location.LocationManager import android.os.Bundle import android.os.Looper import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment 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 com.moapp.guardaroundd.R import com.moapp.guardaroundd.databinding.FragmentMapBinding import com.moapp.guardaroundd.utils.Constants.DEFAULT_ZOOM import com.moapp.guardaroundd.utils.Constants.LOCATION_PERMISSION_REQUEST_CODE import com.moapp.guardaroundd.utils.createAlertEnableLocation class MapFragment : Fragment(), OnMapReadyCallback { private lateinit var mMap: GoogleMap private lateinit var binding: FragmentMapBinding private lateinit var fusedLocationClient: FusedLocationProviderClient private var mLocationPermissionsGranted = false // 新增:定位请求配置 private lateinit var locationRequest: LocationRequest // 新增:定位结果回调 private lateinit var locationCallback: LocationCallback override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentMapBinding.inflate(layoutInflater) val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this) fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) // 初始化定位配置 initLocationConfig() return binding.root } // 新增:初始化定位请求和回调逻辑 private fun initLocationConfig() { locationRequest = LocationRequest.create().apply { // 定位间隔,单位毫秒,可按需调整 interval = 5000 // 最快定位间隔 fastestInterval = 2000 // 高精度定位模式,优先使用GPS priority = LocationRequest.PRIORITY_HIGH_ACCURACY } // 定位结果回调 locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { super.onLocationResult(locationResult) val location = locationResult.lastLocation ?: return // 拿到实时定位后执行逻辑 moveCamera(LatLng(location.latitude, location.longitude)) mMap.isMyLocationEnabled = true // 如果只需要一次定位,拿到结果后就停止定位,降低功耗 stopLocationUpdate() } } } override fun onMapReady(googleMap: GoogleMap) { mMap = googleMap getLocationPermission() } private fun isLocationEnabled(): Boolean { val locationManager = activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager? // 避免空指针强转崩溃 return locationManager?.let { it.isProviderEnabled(LocationManager.GPS_PROVIDER) || it.isProviderEnabled(LocationManager.NETWORK_PROVIDER) } ?: false } private fun moveCamera(latLng: LatLng) { mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM)) } // 修改:替换原有缓存定位逻辑为实时定位请求 private fun getLocation() { if (isLocationEnabled()) { if (ActivityCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { return } fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() ) } else { createAlertEnableLocation(requireContext()) } } // 新增:停止定位请求 private fun stopLocationUpdate() { fusedLocationClient.removeLocationUpdates(locationCallback) } private fun getLocationPermission() { if (ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { mLocationPermissionsGranted = true getLocation() } else { ActivityCompat.requestPermissions( requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE ) } } // 修复:权限授权后主动调用定位 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { mLocationPermissionsGranted = false when (requestCode) { LOCATION_PERMISSION_REQUEST_CODE -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mLocationPermissionsGranted = true getLocation() } } } } // 新增:页面不可见时停止定位,避免内存泄漏和不必要的功耗 override fun onStop() { super.onStop() stopLocationUpdate() } }
注意事项
- 确保你module级的
build.gradle文件中已经引入了定位依赖:
版本号可以替换为官方最新稳定版implementation "com.google.android.gms:play-services-location:21.0.1" - 如果你的App适配Android 12及以上系统(targetSdk >= 31),需要在
AndroidManifest.xml中补充对应定位权限声明,后台定位还需要额外申请ACCESS_BACKGROUND_LOCATION权限 - 可根据业务需求调整定位间隔,不需要高频定位时尽量调大间隔减少功耗
内容的提问来源于stack exchange,提问作者user15608723
相关产品推荐
相关产品推荐

