无法使用FusedLocationProviderClient获取当前(实时)位置



经过2天的挣扎,我不得不问这个问题。我一直在搜索StackOverflow,但没有解决方案似乎适合我。我不知道为什么。

我试图获得当前设备位置一次:

(a)权限已被授予

(b)用户通过在片段(SelectLocationFragment.kt)中出现的对话框中点击"ok"来启用位置服务

问题:一旦权限被授予,通过在对话框中按下'ok '来启用位置—如果我使用硬编码值,如下面所示:

//currentLatLng = LatLng(51.000, -0.0886)

代替:

currentLatLng = LatLng(mCurrentLocation.latitude,mCurrentLocation.longitude)

很好。但这当然不是理想的。我想实时设备位置使用onLocationCallBack的onLocationResult使用:

fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback, Looper.getMainLooper())

问题是当我尝试使用:

currentLatLng = LatLng(mCurrentLocation.latitude,mCurrentLocation.longitude)

a) onLocationCallBack似乎没有被调用。因此没有调用onLocationResult发生,因此,mCurrentLocation仍然uninitialised。因此我得到了错误:

kotlin.UninitializedPropertyAccessException: lateinit property mCurrentLocation has not been initialized

This my onMapReady()

@SuppressLint("MissingPermission")
override fun onMapReady(gMap: GoogleMap) {
isPoiSelected = false
map = gMap
**checkPermissionsAndDeviceLocationSettings()**
setMapStyle(map)
setPoiClick(map)
setMapLongClick(map)
}

这是checkPermissionAndDeviceLocationSettings():

@SuppressLint("MissingPermission")
private fun checkPermissionsAndDeviceLocationSettings() {
if (isPermissionGranted()) {
checkDeviceLocationSettings()
} else {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_PERMISSION_LOCATION
)
}
}

这是checkDeviceLocationSettings:

private fun checkDeviceLocationSettings(resolve: Boolean = true) {
val locationRequest = LocationRequest.create().apply {
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
interval = 10000L
}
val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val settingsClient = LocationServices.getSettingsClient(requireActivity())
val locationSettingsResponseTask =
settingsClient.checkLocationSettings(builder.build())
locationSettingsResponseTask.addOnFailureListener { exception ->
if (exception is ResolvableApiException && resolve) {
try {
startIntentSenderForResult(
exception.resolution.intentSender,
REQUEST_TURN_DEVICE_LOCATION_ON, null, 0, 0, 0, null
)
} catch (sendEx: IntentSender.SendIntentException) {
Log.d(
SaveReminderFragment.TAG,
"Error getting location settings resolution: " + sendEx.message
)
}
} else {
Snackbar.make(
activity!!.findViewById<CoordinatorLayout>(R.id.myCoordinatorLayout),
R.string.location_required_error, Snackbar.LENGTH_INDEFINITE
).setAction(android.R.string.ok) {
checkDeviceLocationSettings()
}.show()
}
}
locationSettingsResponseTask.addOnSuccessListener {
Log.e(TAG, "SUCCESSFUL!")
Toast.makeText(requireContext(), "TOAST", Toast.LENGTH_SHORT).show()
enableLocation(locationRequest)
showSnackBar(getString(R.string.select_location))
}
}

这是enableLocation:

@SuppressLint("MissingPermission")
private fun enableLocation(locationRequest: LocationRequest) {
Log.e(TAG, "Inside Enable Location Start")
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
Log.e(TAG, "Inside on Location Result")
val locationList = locationResult.locations
Log.e(TAG, "${locationResult.locations}")
if(locationList.isNotEmpty()){
val location = locationList.last()
Log.i("MapsActivity", "Location: " + location.latitude + " " + location.longitude)
mCurrentLocation = location
}
fusedLocationClient.removeLocationUpdates(locationCallback)
}
}
map.isMyLocationEnabled = true
val locationResult: Task<Location> = fusedLocationClient.lastLocation
locationResult.addOnCompleteListener(OnCompleteListener<Location?> { task ->
if (task.isSuccessful) {
Log.e(TAG, locationResult.result?.latitude.toString())
// Set the map's camera position to the current location of the device.
if (task.result != null) {
mCurrentLocation = task.result!!
val latLng = LatLng(
mCurrentLocation.latitude,
mCurrentLocation.longitude
)
val update = CameraUpdateFactory.newLatLngZoom(
latLng,
18f
)
Toast.makeText(requireContext(), "CAMERA MOVING", Toast.LENGTH_SHORT).show()
map.animateCamera(update)
} else {
Log.e(TAG, " Task result is null")
//Need to do something here to get the real time location
fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback, Looper.getMainLooper())
currentLatLng = LatLng(mCurrentLocation.latitude,mCurrentLocation.longitude)
//currentLatLng = LatLng(51.000, -0.0886)
val update = CameraUpdateFactory.newLatLngZoom(currentLatLng, 18f)
map.animateCamera(update)
}
} else {
Log.e(TAG, "Unsuccessful Task result")
Toast.makeText(requireContext(), "ENABLE LOCATION ELSE", Toast.LENGTH_LONG).show()
}
})
}

有没有上帝派人来帮我解决这个问题?我开始渐渐衰弱了。

如果你们需要查看整个文件:

提前谢谢你。

FusedLocationProvider可以返回空的Location,特别是第一次获取Location时。因此,正如您所发现的,简单地在结果为null时返回将迫使requestLocationUpdates()再次触发并第二次实际获取有效的Location

我认为你也可以强迫FusedLocationProviderLocation的第一次,如果你只是打开谷歌地图应用程序,等待它获得GPS锁定。当然,你不会希望你的用户为了你的应用程序的工作而不得不执行这个过程,但它仍然是很好的调试。

原因似乎是FusedLocationProvider试图返回最近为设备获取的Location。如果这个Location太旧了,从未被获取过,或者用户在他们的手机上打开/关闭了位置选项,它只返回null。

最新更新