I am making an app using fusedLocationProviderClient to locate the user.
First, I try to retrieve last known location and then, if it isn't available I am making a request location.
Here is the issue, when I run the app, it doesn't trigger onLocationResult() method from the Callback.
So here's the logic of the code :
I tried to get the last known location, if it returns null, the method "checkIfCurrentLocationSettingsSatisfied" is summoned.
This method verifies if the phone's location is enabled, if not an other activity is launched and asks the user to allow location. The result code is checked on the "onActivityResult" method.
Furthermore, the location request is initiated. After that, the location Callback is also initiated.
Last of all, the fusedLocationProviderClient variable is set with the location request and the callback.
When the phone has a last known location, there is no problem. It's only when it tries to get a location.
In the manifest, I gave the " android.permission.ACCESS_FINE_LOCATION " permission. I found a topic that has an issue like mine but I tried every solutions proposed and it hasn't resolving my issue. Here is the topic : LocationCallback not getting called
Here is the code :
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
googleMap.setMyLocationEnabled(true);
googleMap.setOnMapLoadedCallback(this);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.setOnMarkerClickListener(this);
getDeviceLocation();
}
private void getDeviceLocation(){
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getContext());
try{
if(mLocationPermissionGranted){
Task location = fusedLocationProviderClient.getLastLocation();
location.addOnCompleteListener(task -> {
if(task.isSuccessful()){
Location currentLocation = (Location) task.getResult();
if(currentLocation == null){
builder = new LocationSettingsRequest.Builder();
checkIfCurrentLocationSettingsSatisfied();
}else{
moveCamera(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()));
}
}else{
Toast.makeText(getContext(), R.string.couldnt_get_location, Toast.LENGTH_SHORT).show();
}
});
}
}catch (SecurityException e){
e.printStackTrace();
}
}
private void moveCamera(LatLng latLng){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM));
}
public void checkIfCurrentLocationSettingsSatisfied(){
SettingsClient client = LocationServices.getSettingsClient(getActivity());
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(locationSettingsResponse -> {
createLocationRequest();
});
task.addOnFailureListener(getActivity(), e -> {
if (e instanceof ResolvableApiException) {
try {
ResolvableApiException resolvable = (ResolvableApiException) e;
startIntentSenderForResult(resolvable.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null);
} catch (IntentSender.SendIntentException sendEx) {
sendEx.printStackTrace();
}
}
});
}
private void createLocationRequest() {
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2000);
initializeLocationCallback();
}
private void initializeLocationCallback() {
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
Toast.makeText(getContext(), R.string.couldnt_get_location, Toast.LENGTH_SHORT).show();
return;
}
for (Location location : locationResult.getLocations()) {
// It never gets here
moveCamera(new LatLng(location.getLatitude(),location.getLongitude()));
}
}
};
startLocationUpdates();
}
private void startLocationUpdates() {
fusedLocationProviderClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper());
}
Related
I have a code that makes location requests for the user, everything works fine as long as the user is already in the "location" mode is active, however, if the "location" mode is not activated in the device notification bar location returns null, I know that when we disable the option the cache of locations is cleared, how could I ask the user to activate the option for q then I request the getLastLocation?
fusedLocationProviderClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
localidade = task.getResult();
if(localidade != null){
try {
locFromLatLon = new Geocoder(AddAnuncioActivity.this, Locale.getDefault());
List<Address> addresses = locFromLatLon.getFromLocation(localidade.getLatitude(), localidade.getLongitude(), 1);
Log.i("VALORZAS", addresses.get(0).getCountryName());
} catch (IOException e) {
e.printStackTrace();
}
}else{
// Put some here whenlocation is null -- this happens when the Location option in notification bar of // user is unabled
}
}
});
This only work if the option from the image is enabled, if this option is off, the getResult returns null.
My onResume function:
#Override
protected void onResume() {
super.onResume();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(60000);
locationRequest.setFastestInterval(5000);
LocationCallback locationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult == null) {
Toast.makeText(getApplicationContext(), "Localidade ainda vazia", Toast.LENGTH_LONG).show();
return;
}
for (Location location : locationResult.getLocations()) {
}
}
};
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);
}
You can try with LocationManager:
final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
//Call Alert or use android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS
}
Refer the Documentation
I am using FusedLocationProvider to get the last location of the phone. Unfortunately the returned location is far from being accurate and it is not updating!.
Even When I call requestlocationupdates,the OnlocationResult never being called with PRIORITY_HIGH_ACCURACY. BUT it called ONLY once with PRIORITY_BALANCED_POWER_ACCURACY.
protected void startLocationUpdates() {
// Create the location request to start receiving updates
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(1000);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task =settingsClient.checkLocationSettings(locationSettingsRequest);
task.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
Log.i("SRV", "onSuccess: Location settings are satisfied");
}
});
task.addOnFailureListener( new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
Log.i("SRV", "onFailure: ");
}
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// Activity#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for Activity#requestPermissions for more details.
initialized = false;
//return;
}
}
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mFusedLocationClient.requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Log.i("SRV", "onLocationResult is called ");
if (locationResult == null) {
return;
}
for (Location location : locationResult.getLocations()) {
if (location != null) {
Log.i("SRV", "My new location is " + location.getLatitude() + " " + location.getLongitude());
onLocationChanged(location);
}
}
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
Log.i("SRV", "onLocationAvailability is called ");
}
},
Looper.myLooper());
//get last location
mFusedLocationClient.getLastLocation().addOnSuccessListener(location -> {
if (location != null) {
_phoneLocation = location;
Log.i("SRV", "getLastLocation is called : My position " + location.getLatitude() + " " + location.getLongitude());
}
});
Log.i("SRV", "Startlocation updated was completed succesfully");
}
I expect the OnlocationResult to be called and updated very 5 seconds.
It turns out that it is a stupid thing. We spent too much time on this. I had some issues of checking the permissions and allowing it.
Here I post the final code that works perfectly. Make sure to allow the location permission when it prompts. If you are debugging many times, It is recommended to uninstall the app first to allow the permission again.
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION},
1);
} else if (mMap != null) {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
I have recently stared to get issues as my FusedLocationProviderClient doesn't call the onLocationResult() method of LocationCallback when the device location is already enabled but has no problems to do so when I ask user to enable the location himself first (disabled at first). Below I am posting my code (I do not show how I obtain location permission beforehand) called from onCreate():
public void onReady() {
LocationRequest locReq = LocationRequest.create();
LocationSettingsRequest request = new LocationSettingsRequest.Builder()
.addLocationRequest(locReq)
.build();
LocationServices.getSettingsClient(this)
.checkLocationSettings(request)
.addOnCompleteListener(this::handleSettingsResponse);
}
private void handleSettingsResponse(Task<LocationSettingsResponse> task) {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
if (response != null) {
LocationSettingsStates states = response.getLocationSettingsStates();
if (states.isLocationPresent() && states.isLocationUsable()) {
findLocation();
} else {
failure()
}
}
} catch (ApiException e) {
copeWithFailure(e);
}
}
private void copeWithFailure(Exception e) {
if (e instanceof ResolvableApiException) {
try {
((ResolvableApiException) e).startResolutionForResult(this, REQUEST_RESOLUTION);//I call findLocation() if successful
} catch (IntentSender.SendIntentException e1) {
failure()
}
}
}
private void findLocation() {
FusedLocationProviderClient client =
LocationServices.getFusedLocationProviderClient(this);
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
startingLatitude = location.getLatitude();
startingLongitude = location.getLongitude();
}}
LocationRequest locaReq = LocationRequest()
.setNumUpdates(1)
.setExpirationDuration(5500)
.setInterval(5000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
client.requestLocationUpdates(locaReq,
mLocationCallback, Looper.getMainLooper())
.addOnFailureListener(this, e -> {
});
}
This worked without problems before with pre-enabled location.
I have the following functions that retrive the current position of the device. My problem is that I am unable to run this Service the background(I tried using Service intent but to no avail).
private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 10 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000; /* 2 sec */
protected void startLocationUpdates() {
// Create the location request to start receiving updates
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}else{
// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
}
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// do work here
Log.d("test",locationResult.getLastLocation().toString());
onLocationChanged(locationResult.getLastLocation());
}
},
Looper.myLooper());
}
public void onLocationChanged(Location location) {
// New location has now been determined
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
// You can now create a LatLng Object for use with maps
}
public void getLastLocation() {
// Get last known recent location using new Google Play Services SDK (v11+)
FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}else{
// locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
}
locationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
onLocationChanged(location);
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("MapDemoActivity", "Error trying to get last GPS location");
e.printStackTrace();
}
});
}
at the moment I start the location update Service trough the startLocationUpdates(); function. I am open to any suggestions as long as they retain the current functionality of the Service. Sorry if the question seems stupid but I am very new to android.
Use like this
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
Intent ServiceG = new Intent(context, ClipboardService.class);
context.startService(ServiceG);
} else {
Intent ServiceG = new Intent(context, ClipboardJobService.class);
//context.startService(ServiceG);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(ServiceG);
}else {
context.startService(ServiceG);
}
}
I used to use FusedLocationApi until I learned that it is deprecated (see references below). It was simple to implement. As the documentation says you need to use it in conjunction with GoogleApiClient
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,
locationRequest, this);
I recently changed to FusedLocationProviderClient (see reference below) Following a tutorial I was able to successfully get FusedLocationProviderClient working
Tutorial: https://github.com/codepath/android_guides/wiki/Retrieving-Location-with-LocationServices-API
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// do work here
onLocationChanged(locationResult.getLastLocation();
}
},
Looper.myLooper());
The issue I am running into is the Looper thread. Even with the application in the background, the Looper thread continues to run. I would like to pause location updates when the application is in the background and then resume location updates when the application is in the foreground. How can I achieve this?
References:
https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi
https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient
You just need to call mFusedLocationClient.removeLocationUpdates(mLocationCallback) in onPause() of your Activity. However, there is a bit more to it than just that.
Use member variables for the FusedLocationProviderClient and LocationRequest in your main activity:
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;
public class MainActivity extends AppCompatActivity
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
FusedLocationProviderClient mFusedLocationClient;
LocationRequest mLocationRequest;
//..........
Use a member variable for the LocationCallback as well:
LocationCallback mLocationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
Log.i("MainActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
}
};
};
Then, assign mFusedLocationClient in onCreate() :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
requestLocationUpdates();
//...............
}
Then in onResume(), if theFusedLocationProviderClient is set up, then use it.
#Override
public void onResume() {
if (mFusedLocationClient != null) {
requestLocationUpdates();
}
}
public void requestLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(120000); // two minute interval
mLocationRequest.setFastestInterval(120000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
}
And finally, in onPause(), call removeLocationUpdates():
#Override
public void onPause() {
super.onPause();
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
After getting location just remove mFusedLocationClient.removeLocationUpdates as he mentioned in above answers.
if (mFusedLocationClient != null)
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
Looper will be called requestLocationUpdates until you remove it.
In my problem, I did as I mention above. Below is my code.
mFusedLocationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
mLocation = location;
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
} else {
startLocationUpdates();
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(HomeActivity.this, "Error trying to get last GPS location", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
});
and below is my requestLocationUpdates so I will get a request until the location is available.
private void startLocationUpdates() {
mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.i(TAG, "All location settings are satisfied.");
getPackageManager().checkPermission(Manifest.permission.ACCESS_FINE_LOCATION, getPackageName());
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback, Looper.myLooper());
getLastLocationNewMethod();
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade " +
"location settings ");
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(HomeActivity.this, 0x1);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Log.e(TAG, errorMessage);
Toast.makeText(HomeActivity.this, errorMessage, Toast.LENGTH_LONG).show();
// mRequestingLocationUpdates = false;
}
getLastLocationNewMethod(); // this method is where I can get location. It is calling above method.
}
});
}
Note: For more information here is GitHub Repo LINK