Reputation: 3512
Affected devices so far:
Use: In order to request location updates, I check that the location settings are adequate beforehand. If not, I show a small text, that the services must be enabled for my feature. If the user clicks on it, the system dialog to enable the location service will be prompted.
How I run the check:
I run the check through LocationSettingsRequest
and LocationServices
and
handle the ResolvableApiException
. If the Service is disabled by the user,
then on all my devices this will show the System Dialog, asking the user to enable
the service (and enables it, if okay is clicked).
What happens instead on Redmi:
But for whatever reason, on Xiamoi Redmi Note 7, the checkLocationSettings
will always return with an ResolvableApiException
, even if the service
is already enabled. The Dialog won't appear and directly return a positive result
(sure, because the service is enabled).
Hence, the user is stuck and clicks forever on "enable".
Does somebody has any information why the LocationSettingsRequest
is not working
properly on those devices and knows how to fix it?
Example Code snippet
void enableLocationSettings(onLocationServiceRequiredCallback: ICallback) {
LocationRequest locationRequest = LocationRequest.create()
.setInterval(LOCATION_UPDATE_INTERVAL)
.setExpirationDuration(LOCATION_UPDATE_EXPIRATION_DURATION)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
LocationServices
.getSettingsClient(this)
.checkLocationSettings(builder.build())
.addOnSuccessListener(this, (LocationSettingsResponse response) -> {
// update location as usual
})
.addOnFailureListener(this, error -> {
if (error instanceOf ApiException) {
int statusCode = error.statusCode;
if(statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) {
if(error instanceOf ResolvableApiException) {
PendingIntent resolution = error.resolution
// This will trigger the system dialog, see below
onLocationServiceRequiredCallback(resolution);
}
}
}
// error callback
});
Unfortunately the code for the callback will now be kotlin. Sorry for that. I can only post "example code snippets", since this is work related.
It uses ActivityResultContracts.StartIntentSenderForResult
to start
the system dialog.
resolution
is the PendingIntent from above.
The contract:
private val locationServiceContract = registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
) { activityResult ->
lifecycleScope.launchWhenResumed {
val result = if (activityResult.resultCode == Activity.RESULT_OK) {
// This will retrigger the location fetch (looping)
enableLocationSettings(...)
} else {
// Do nothing
}
}
}
After the callback from above is called, this will get executed:
locationServiceContract.launch(
IntentSenderRequest.Builder(
resolution
).build()
)
Dump of LocationSettingsStates
, aquired using the deprecated LocationSettings API (which is using GoogleApiClient):
isGpsPresent: true,
isGpsUsable: false,
isLocationPresent: true,
isLocationUsable: true,
isNetworkLocationPresent: true,
isNetworkLocationUsable: true
Upvotes: 3
Views: 1124
Reputation: 7230
After doing a good amount of research I got a solution for this ...
The problem is basically, if the LocationSettingsStatusCodes.RESOLUTION_REQUIRED == true
then the next consecutive call you make will always result in the same output
i.e if you are calling this function recursively you will get RESOLUTION_REQUIRED always so what you can do is modify your contract to something like this
private val locationServiceContract = registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
) { activityResult ->
lifecycleScope.launchWhenResumed {
val result = if (activityResult.resultCode == Activity.RESULT_OK) {
// Dont call this as it will retrigger the location fetch (looping)
// enableLocationSettings(...)
requestForLocationUpdates() // create this method see method body below
} else {
// Do nothing
}
}
}
requestForLocationUpdates()
private fun requestForLocationUpdates() {
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
if (locationResult.locations.size > 0) {
// update location as usual using locationResult.locations[0] or other item
fusedLocationClient.removeLocationUpdates(locationCallback)
}
}
}
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
Upvotes: 0
Reputation: 3258
Hi I use different code in order to check if GPS is enabled on a device. maybe its worth for you to try it out and see if it resolves your issue.
private boolean isLocationEnabled(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return LocationManagerCompat.isLocationEnabled(locationManager);
}
I then send the user to settings through a dialog using
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
I bet you are doing the same. After sending the user to enable GPS you can just run the method a second time on resume
let me know if this helps
Upvotes: 1