Kotlin: FusedLocationProviderClient.removeLocationUpdates always return false - android

This question seems like a duplicate of this one but trust me I've tried the solutions but couldn't figure out the reason behind my problem. I'm a newbie in Kotlin and I'm requesting location updates with the FusedLocationProvider.
Relevant Code:
private lateinit var mLocationCallback: LocationCallback? = null
private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient
private lateinit var mLocationRequest: LocationRequest
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(mContext)
// Create a LocationRequest
mLocationRequest = LocationRequest.create().apply {
interval = java.util.concurrent.TimeUnit.SECONDS.toMillis(1000)
smallestDisplacement = 0f
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates more frequently than this value.
fastestInterval = java.util.concurrent.TimeUnit.SECONDS.toMillis(1000)
// Sets the maximum time when batched location updates are delivered. Updates may be
// delivered sooner than this interval.
maxWaitTime = java.util.concurrent.TimeUnit.MINUTES.toMillis(1000)
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
// Initialize the LocationCallback.
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
// Normally, you want to save a new location to a database. We are simplifying
// things a bit and just saving it as a local variable, as we only need it again
mCurrentLocation = locationResult.lastLocation
//Get Date Time
// saveLatLngData(this,mCurrentLocation.latitude.toString(),mCurrentLocation.longitude.toString())
mTimeStamp = Calendar.getInstance().time
Log.d(TAG, "LocationCallback=> TimeStamp: " + mDateFormat!!.format(mTimeStamp) + " Latitude: " + mCurrentLocation!!.latitude + " - Longitude: " + mCurrentLocation!!.longitude + " - Altitude: " + mCurrentLocation!!.altitude)
mNotificationText = mDateFormat!!.format(mTimeStamp) + "\nLat: ${locationResult.lastLocation.latitude} | Long: ${locationResult.lastLocation.longitude}"
createForegroundInfo()
}
}
// Subscribe to location changes.
if (ActivityCompat.checkSelfPermission(mContext,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mContext,Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if(mFusedLocationProviderClient != null)
{
mFusedLocationProviderClient.requestLocationUpdates(mLocationRequest,mLocationCallback,Looper.getMainLooper())
Log.d(TAG, "startMonitoring: mFusedLocationProviderClient is registered now.")
}
else
{
Log.d(TAG, "startMonitoring: mFusedLocationProviderClient is not initialized!")
}
return
}
//STOPPING LOCATION UPDATES (AFTER GETTING SOME VALUES) USING THE FOLLOWING CODE
if (mFusedLocationProviderClient != null) {
try {
val voidTask: Task<Void> = mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback)
if (voidTask.isSuccessful)
{
Log.d(TAG, "stopMonitoring: removeLocationUpdates successful.")
}
else
{
Log.d(TAG, "stopMonitoring: removeLocationUpdates updates unsuccessful! " + voidTask.toString())
}
}
catch (exp: SecurityException)
{
Log.d(TAG, "stopMonitoring: Security exception.")
}
}
Expected Behavior:
Upon calling the mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback) method, the location updates should be removed and stopMonitoring: removeLocationUpdates successful. should be printed on the logger.
Problem:
Location updates are not being removed as I see stopMonitoring: removeLocationUpdates updates unsuccessful! on the logger which means that the else condition is executed.
I tried to find out the reason and applied some solutions as well. Please guide me a little about the possible options I have.

A Task takes some time to complete. You expect it to be finished right away, which is very unlikely to happen. You should do the check like this:
try {
val voidTask: Task<Void> = mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback)
voidTask.addOnCompleteListener {
if(it.isSuccessful) {
Log.d("Location", "stopMonitoring: removeLocationUpdates successful.")
} else {
Log.d("Location", "stopMonitoring: removeLocationUpdates updates unsuccessful! " + voidTask.toString())
}
}
} catch (exp: SecurityException){
Log.d("Location", "stopMonitoring: Security exception.")
}

Related

Unable to get current (real time) location using FusedLocationProviderClient

After 2 days of struggle, I have been forced to ask this question. I have been searching StackOverflow but no solution seems to work for me. I don't know why.
I am trying to get the current device location once:
(a) the permissions have been granted
(b) user has enabled location service by tapping 'Okay' in the dialogue box that appears in the fragment (SelectLocationFragment.kt)
The issue: Once the permissions are granted, location is enabled by pressing 'okay' in the dialogue - If I use hard coded values like here:
//currentLatLng = LatLng(51.000, -0.0886)
instead of :
currentLatLng = LatLng(mCurrentLocation.latitude,mCurrentLocation.longitude)
It works fine. But this is not ideal of course. I'd like real time device location using onLocationCallBack's onLocationResult using:
fusedLocationClient.requestLocationUpdates(locationRequest,locationCallback, Looper.getMainLooper())
The problem is when I try to use:
currentLatLng = LatLng(mCurrentLocation.latitude,mCurrentLocation.longitude)
a) onLocationCallBack does not seem to be called. And therefore no call to onLocationResult happens, and therefore, mCurrentLocation remains uninitialised. And hence I get the error :
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)
}
This is checkPermissionAndDeviceLocationSettings():
#SuppressLint("MissingPermission")
private fun checkPermissionsAndDeviceLocationSettings() {
if (isPermissionGranted()) {
checkDeviceLocationSettings()
} else {
requestPermissions(
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_PERMISSION_LOCATION
)
}
}
This is 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))
}
}
This is 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()
}
})
}
Is there any God sent man out there to help me resolve this issue. I am beginning to fade away.
If you guys need to see the entire file:
Thank you in advance.
FusedLocationProvider can return a null Location, especially the first time it fetches a Location. So, as you have found, simply returning when the result is null will force requestLocationUpdates() to fire again and actually fetch a valid Location the second time.
I think you can also force FusedLocationProvider to have a Location the first time if you just open the Google Maps app and wait for it to obtain a GPS lock. Of course, you wouldn't want your users to have to perform this process in order for your app to work, but it's still good to know for debugging.
The cause of this seems to be that FusedLocationProvider tries to return the most recently fetched Location for the device. If this Location is too old, has never been fetched, or the user toggled on/off the Location option on their phone, it just returns null.

How can i get current GPS location ? (not lastknown)

i am trying to get user's location using only GPS provider. i don't want my app to get the last known location or request for location updates after a particular period of time or when location is changed.is there any way that can give me current location on button press ??? ... i am a beginner, i have tried LocationManager API from android studio and it returns network provided location fine but dosent work when using GPS . here is my code :
fun getlocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), locationPermissionCode)
}
else
{
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
// val listener = locationListener()
val gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
val network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
//if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N)
if (gps || network) {
if (network) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 5F, this)
}
if (gps) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 5F, this)
}
}
else {
val AlertDialog = AlertDialog.Builder(this)
AlertDialog.setTitle("GPS is Disabled")
AlertDialog.setMessage("Do you want enable GPS ?")
AlertDialog.setPositiveButton("Yes") { dialougeInterface: DialogInterface, i: Int ->
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
dialougeInterface.dismiss()
}
AlertDialog.setNegativeButton("No") { dialouge: DialogInterface, i: Int ->
dialouge.dismiss()
}
AlertDialog.show()
}
}
}
i have added location listener in the parent class " class AddCustomer : AppCompatActivity() , LocationListener "
in override function :
override fun onLocationChanged(location: Location) {
locationx.text = location.latitude.toString() +" , "+ location.longitude.toString()
}
should i use "getcurrentlocation()" method from "LocationManager" ?
I don't know if you are getting your last location or not. Here's the answer when you are not getting anything at all from the gps provider.
Making this block like this will only make you get your location via gps.
if (gps) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 5F, this)
}
The above can return when your device's GPS chipset feels like it's getting signal from the GPS, so when inside a building, it will likely be not getting any responds.
Go outside and try it out.
In your usecase, pressing a button to get an accurate location, in case the user can't receive any signal, you should provide a callback for timeout.
private val mHandler = Handler(Looper.getMainLooper())
private val mTimeoutRunnable = Runnable {
//stopLoading
//Toast the user to try it somewhere else
}
fun askGsp() {
mHandler.postDelayed(mTimeoutRunnable, 5 * 1000) //time out in 5 seconds
//ask for gps update like the code above
//...
override fun onLocationChanged(location: Location) {
mHandler.removeCallbacks(mTimeoutRunnable) //remove timeout action
locationx.text = location.latitude.toString() +" , "+
location.longitude.toString()
}
}

Get location in android (problems with callback)

I'm trying to get the user's new location.
This is the code I have so far:
private fun getNewLocation() {
Log.d(TAG, "getNewLocation: started")
locationRequest = LocationRequest()
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest.interval = 0
locationRequest.fastestInterval = 0
locationRequest.numUpdates = 1
fusedLocationProviderClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.myLooper()
)
Log.d(TAG, "getNewLocation: finished")
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
Log.d(TAG, "locationCallback: onLocationResult started")
val newLocation = locationResult.lastLocation
Log.d(TAG, "locationCallback: before setting new data latitude = $latitude, longitude = $longitude")
// set new location
latitude = newLocation.latitude.toString()
longitude = newLocation.longitude.toString()
locationName = getLocationName(newLocation.latitude, newLocation.longitude)
Log.d(TAG, "getLastLocation: new location were set latitude = $latitude, longitude = $longitude")
requestAPI()
}
}
For some reason, when I test it on a physical device getNewLocation() doesn't call onLocationResult
so my Logs look like this:
D/MainActivity: getNewLocation: started
D/MainActivity: getNewLocation: finished
Instead of:
D/MainActivity: getNewLocation: started
D/MainActivity: getNewLocation: finished
D/MainActivity: locationCallback: onLocationResult started
D/MainActivity: locationCallback: latitude = 64.49273, longitude = 40.596625
I've also tried to set newLocation in locationCallback like this:
val newLocation = locationResult.locations[0]
But I have the same result since the problem is in fact that getNewLocation() doesn't call onLocationResult
Can anyone please help me to understand the reason why is it happening this way and how can I fix it?
Thanks!
you should check location settings before request a new location
private suspend fun checkSettings(locationRequest: LocationRequest) {
val settingsRequest = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
.build()
try {
LocationServices
.getSettingsClient(this)
.checkLocationSettings(settingsRequest)
.await()
// location is turned on
} catch (e: ResolvableApiException) {
// location is turned off. Prompt the user to enable it
e.startResolutionForResult(this, CODE)
}
}
Also if you are using the latest version of play-services-location, there is a easy way to get a new location
LocationServices
.getFusedLocationProviderClient(this)
.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, null)

How To Get Compiler To Wait For OnCompleteListener Kotlin

I'm using this function to get the users location and then return the location to another function as argument. However, the compiler does not wait for the OnComleteListener to finish before it returns null - since the location variable was initialised as null.
Can anyone help me get the compiler to wait for the location result from the listener? I am getting a location from the device as I am able to print it in a text view.
Here is the function I am referring to:
#SuppressLint("MissingPermission", "SetTextI18n")
fun getLastLocation(): Location? {
var holder: Location? = null
Log.e(TAG,"CALLED")
if(CheckPermission()) {
if(isLocationEnabled()) {
fusedLocationProviderClient.lastLocation.addOnCompleteListener {task ->
var location = task.result
Log.e(TAG,"Location: $location")
if(location == null) {
getNewLocation()
} else {
holder = location
Log.e(TAG, "Holder1 = $holder")
locationText.text = "Your current coordinates are :\nLat: " + location.latitude + " ; Long: " + location.longitude
}
}
Log.e(TAG, "Holder2 = $holder")
} else {
Toast.makeText(this, "Please enable your location service", Toast.LENGTH_LONG).show()
}
} else {
RequestPermission()
}
Log.e(TAG, "Holder3 = $holder")
return holder
}
As already commented, you can use suspendCoroutine to asynchronously (suspensive) wait for the completion.
suspend fun <T> Task<T>.await(): T {
if (isComplete) {
val e = exception
return if (e == null) {
if (isCanceled) {
throw CancellationException(
"Task $this was cancelled normally.")
} else {
result
}
} else {
throw e
}
}
return suspendCancellableCoroutine { cont ->
addOnCompleteListener {
val e = exception
if (e == null) {
if (isCanceled) cont.cancel() else cont.resume(result)
} else {
cont.resumeWithException(e)
}
}
}
}
// Usage:
try{
val location = fusedLocationProviderClient.lastLocation.await()
} catch(e:Exception){
//handle exception
}
// do something with location, that should be executed after location has fetched
If you don't run the code to await inside a coroutine, then you can wrap the code with runBlocking to synchronously wait (by blocking current thread).
val location = runBlocking { fusedLocationProviderClient.lastLocation.await() }
// do something with location, that should be executed after location has fetched
I suggest to make better use of Activity Life Cycle. Its one of the basic yet fundamental about an app.
This shows how onCreate, onStart, onPause, onResume etc. works.
There are a lot of tutorials showing how one can utilize this, and its very easy to understand. And i think its a lot more convenient than OnCompleteListener, both for the short run and long run.

The last known location is lost when we are not in getLastLocation() - Android

I am trying to create a method that will get the last known location and assign that value to a global variable that I will use later. I am following this training.
In the end, this is the code that I've wrote:
public void getCurrentLocation() {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
fusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
mCurrentLocation = new Location(location);
System.out.println("In method getCurrentLocation: Latitude = " + location.getLatitude() + " Longitude = " + location.getLongitude());
System.out.println("In method getCurrentLocation for mCurrentLocation: Latitude = " + mCurrentLocation.getLatitude() + " Longitude = " + mCurrentLocation.getLongitude());
} else {
Toast.makeText(MainActivity.this, "Can't get the current location", Toast.LENGTH_SHORT).show();
}
}
});
}
The getCurrentLocation() method I will call in the onCreate() method of MainActivity and I can see the prints from the method so my variable got a location, but if I try to use the mCurrentLocation in some other context (for example I want to go to the last known location using this variable) the variable will be null. I am not sure that I need new Location(location), I added it because I thought that my variable will point to a null place in the memory after we exit the method, but it looks that it is not the case (I get the same outcome).
According to official documentation, Last Known Location could be Null in case of:
Location is turned off in the device settings. As it clears the
cache.
The device never recorded its location. (New device)
Google Play services on the device has restarted.
In this case, you should requestLocationUpdates and receive the new location on the LocationCallback.
By the following steps your last known Location never null.
Pre-requisite:
EasyPermission library
Step 1:
In manifest file add this permission
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Step 2:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Create location callback when it's ready.
createLocationCallback()
//createing location request, how mant request would be requested.
createLocationRequest()
//Build check request location setting request
buildLocationSettingsRequest()
//FusedLocationApiClient which includes location
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
//Location setting client
mSettingsClient = LocationServices.getSettingsClient(this)
//Check if you have ACCESS_FINE_LOCATION permission
if (!EasyPermissions.hasPermissions(
this#MainActivity,
Manifest.permission.ACCESS_FINE_LOCATION)) {
requestPermissionsRequired()
}
else{
//If you have the permission we should check location is opened or not
checkLocationIsTurnedOn()
}
}
Step 3:
Create required functions to be called in onCreate()
private fun requestPermissionsRequired() {
EasyPermissions.requestPermissions(
this,
getString(R.string.location_is_required_msg),
LOCATION_REQUEST,
Manifest.permission.ACCESS_FINE_LOCATION
)
}
private fun createLocationCallback() {
//Here the location will be updated, when we could access the location we got result on this callback.
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
mCurrentLocation = locationResult.lastLocation
}
}
}
private fun buildLocationSettingsRequest() {
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(mLocationRequest!!)
mLocationSettingsRequest = builder.build()
builder.setAlwaysShow(true)
}
private fun createLocationRequest() {
mLocationRequest = LocationRequest.create()
mLocationRequest!!.interval = 0
mLocationRequest!!.fastestInterval = 0
mLocationRequest!!.numUpdates = 1
mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this) {
Log.i(TAG, "All location settings are satisfied.")
startLocationUpdates()
}
.addOnFailureListener(this) { e ->
val statusCode = (e as ApiException).statusCode
when (statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
try {
val rae = e as ResolvableApiException
rae.startResolutionForResult(this#MainActivity, LOCATION_IS_OPENED_CODE)
} catch (sie: IntentSender.SendIntentException) {
}
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
mRequestingLocationUpdates = false
}
}
}
}
private fun startLocationUpdates() {
mFusedLocationClient!!.requestLocationUpdates(
mLocationRequest,
mLocationCallback, null
)
}
Step 4:
Handle callbacks in onActivityResult() after ensuring the location is opened or the user accepts to open it in.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
LOCATION_IS_OPENED_CODE -> {
if (resultCode == AppCompatActivity.RESULT_OK) {
Log.d(TAG, "Location result is OK")
} else {
activity?.finish()
}
}
}
Step 5:
Get last known location from FusedClientApi
override fun onMapReady(map: GoogleMap) {
mMap = map
mFusedLocationClient.lastLocation.addOnSuccessListener {
if(it!=null){
locateUserInMap(it)
}
}
}
private fun locateUserInMap(location: Location) {
showLocationSafetyInformation()
if(mMap!=null){
val currentLocation = LatLng(location.latitude,location.longitude )
addMarker(currentLocation)
}
}
private fun addMarker(currentLocation: LatLng) {
val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
mMap?.clear()
mMap?.addMarker(
MarkerOptions().position(currentLocation)
.title("Current Location")
)
mMap?.moveCamera(cameraUpdate)
mMap?.animateCamera(cameraUpdate)
mMap?.setMinZoomPreference(14.0f);
}
I hope this would help.
Happy Coding 🤓
A few weeks later I came up with some sort of a explanation to what is happening and how I managed to get the result that I want. I only had to do the first 3 steps that #MustafaKhaled wrote in his answer, this will make the mFusedLocationClient global variable to have its getLastLocation() method called (I think this happens because I request location updates, see #MustafaKhaled post).
Now, what we do with the last location? The response is nothing, because we do not handle what will happen if we successfully retrieve the location.
That being said, we will need to add what will happen onSuccess() with the location. In my case, I had to retain the value of the mCurrentLocation so I still need the method from the initial post to be implemented:
public void AddFusedLocationClientOnSuccessListener() {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
mCurrentLocation = location;
}
}
});
}
Here I will be able to do some other things with the location if needed (for example if I want the application to animate to the current location), but later, if I when I use buttons or other graphical elements, I will be able to use the mCurrentLocation variable.
Now, I will be able to call the mCurrentLocation directly in the onCreate()? The answer is NO, because we will have to wait for mFusedLocationClient to successfully get the last known location, otherwise themCurrentLocation will be null, that is the reason in the initial post it did not work, we were not calling the getLastLocation() method until we will get success.
I hope this answer will be helpful for other peoples that encounter this problem and they don't fully understand what happens in the onCreate().

Categories

Resources