I need to update fused location every 1 min and on each 5 meter displacement (I know its bad practice but for the sake of testing and showing in Log ) and i start service by button Pressed as soon as button pressed i got location in logcat but only once. As per Service class the onLocationChanged should called every 1 min but it never calls again even my GPS turn on almost every min and then turn off after while but still there is no Location Update in Logcat.I need service class to keep update location without effecting UI or main thread
Here is logcat which shows location update only once
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service onConnected Calling
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Start Location Update is Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service OnLocationChanged Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Here is Updated Locations: Latitude 28.5XXXXX Longitude 77.2XXXXX
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Sending Location Starting Accuracy is: 37.5
Here is my Service Class
public class Location_Service_background extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static final String TAG = "===Location Service===";
GoogleApiClient apiClient;
Location mCurrentLocation;
LocationRequest locationRequest;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
GoogleApiSetup();
RequestLocationUpdates();
Log.d(TAG,"OnStartCommand Is Calling ");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
if (apiClient.isConnected()){
Log.d(TAG,"Service On Destroy Calling and apiClient is Connected");
StopLocationUpdates();
apiClient.disconnect();
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG,"Service onConnected Calling");
if (mCurrentLocation != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(apiClient);
}
else {
Log.d(TAG,"Start Location Update is Calling");
StartLocationUpdate();
}
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"Service OnConnectionSuspended Calling");
apiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"Service OnLocationChanged Calling");
mCurrentLocation=location;
Log.d(TAG,"Here is Updated Locations: Latitude "+mCurrentLocation.getLatitude()+"Longitude "+mCurrentLocation.getLongitude());
String Latitude= String.valueOf(mCurrentLocation.getLatitude());
String Longitude=String.valueOf(mCurrentLocation.getLongitude());
String Accuracy=String.valueOf(mCurrentLocation.getAccuracy());
Log.d(TAG,"Sending Location Starting"+" "+" Accuracy is: "+mCurrentLocation.getAccuracy());
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG,"Connection Failed Called "+connectionResult);
}
private synchronized void GoogleApiSetup() {
apiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
apiClient.connect();
}
private void RequestLocationUpdates() {
locationRequest = new LocationRequest();
//1 Min = 60 seconds AND 1000 milliseconds in 1 second
locationRequest.setInterval(60 * 1000);//5 Min 300 x 1000=300000
locationRequest.setFastestInterval(60 * 1000);//2 Min
locationRequest.setSmallestDisplacement(5);
locationRequest.setMaxWaitTime(60*1000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void StopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
}
private void StartLocationUpdate() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (apiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, this);
}
else {
Log.d(TAG,"GoogleApiClient is not connected yet.Please Try Again");
apiClient.connect();
}
}
}
Hopefully this helps save someone the frustration i went through on this issue. I am using the FusedLocationAPI to request location updates and GoogleApiClient. I also do this from a Service.
You are not getting any location updates at your timed interval because setSmallestDisplacement() takes absolute priority over the other parameters. So even if you have
this will NEVER be triggered until the smallestDisplacement parameter is met.
The solution to this, is to create two separate LocationRequests... one that is only concerned with distance, and one that is only concerned with time, and use your single GoogleApiClient to create 2 requestLocationUpdates commands, one using the Time LocationRequest, and the other using the Distance LocationRequest.
So your 2 LocationRequests look like this:
Then in your GoogleApiClients onConnected(), you can add the two requestLocationUpdates() calls.
You can use the same or separate LocationListeners to handle the responses for each request. Hope this helps.
Presuming that you are in fact moving the device more than 5 meters between expected updates, I think there might be a problem with the LocationRequest class where the setSmallestDisplacement() method just doesn't work properly... or at least it doesn't work as expected. (I've seen these issues on other posts).
You could always check the distance yourself by removing the setSmallestDisplacement(), and instead doing:
There is also the possiblity that for some reason, the FusedLocationProvider is not able to access your GPS and is instead using wifi or cell tower... in which case, 5m is too small of a distance to specify. Your logs say the accuracy is 37.5 meters, so that doesn't seem accurate enough to be able to measure 5 meters. So... maybe you don't have FINE access permission set in your manifest?
Also could it be a problem with runtime permissions not being done properly? You could temporarily set your target SDK to 22 in order to check this.