1

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();
        }
    }


}
androidXP
  • 1,692
  • 3
  • 27
  • 58
  • Try it without using the setsmallestdisplacement and see what happens – Nerdy Bunz Sep 16 '16 at 03:44
  • It shows calls making to `onLocationUpdate` without `setsmallestdisplacement ` but how can i use regular update with setsmallestdisplacement. Thanks For Help – androidXP Sep 16 '16 at 07:54

3 Answers3

6

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

locationRequestTimeInterval = LocationRequest.create()
    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
    .setInterval(1)    
    .setFastestInterval(1)    
    .setMaxWaitTime(1)    
    .setSmallestDisplacement(5);

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:

locationRequestDistanceInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setFastestInterval(0) // This MUST be set, otherwise no updates
            .setSmallestDisplacement(LOCATION_REQUEST_MIN_DISTNACE);

locationRequestTimeInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL)
            .setFastestInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL);
  • note that the setFastestInterval() value MUST be set on the Distance Request, otherwise the distance request will not be triggered. It does not have to be 0, but this field must be set.

Then in your GoogleApiClients onConnected(), you can add the two requestLocationUpdates() calls.

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestDistanceInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Distance based updates
        }
    }
);

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestTimeInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Time based updates
        }
    }
);  

You can use the same or separate LocationListeners to handle the responses for each request. Hope this helps.

Marlon
  • 1,839
  • 2
  • 19
  • 42
RH201
  • 312
  • 3
  • 16
  • ```.setFastestInterval(0) // This MUST be set, otherwise no updates``` Thanks for this, smallestDisplacement didn't work and the docs don't mention it. – laszlo Mar 09 '20 at 14:43
0

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:

onLocationChanged() {
    double distance = // [ calculate distance between current lat/long and previous lat/long ]
    if (distance > 5 meters) {
        // do your normal onLocationChanged() code here
    }
}

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.

Marlon
  • 1,839
  • 2
  • 19
  • 42
Nerdy Bunz
  • 6,040
  • 10
  • 41
  • 100
  • I am checking it indoors thats why accuracy is that high and i have fine location permission that's why GPS turned on ,coarse Location don't have access to GPS.If i set my location update to 5 meter that's shouldn't stop location update every 1 minute.Its like update location in every 1 min or every 5 meter.if 5 meter is not crossing then have to update every 1 min but its not updating when i use `setsmallestdisplacement ` and as you suggest to calculate distance between 2 points its not possible – androidXP Sep 16 '16 at 11:38
  • Cuz in real conditions i have to set interval long as 10 min or 15 min and what if user move few miles in these time period then i lose the location which he traveled between those time period so i need to stick to API method for sending location after that x meters – androidXP Sep 16 '16 at 11:41
  • Unfortunately I didn't realize that was your understanding of how the setdisplacement method works. From my understanding, the method means: Only fire the onLocationChanged method IF the user has travelled at least X meters since the previous time is was fired. It does NOT mean: fire every 5 meters, because this would require the phone to make constant location monitoring/calculatios, which you are trying to avoid in order to save battery by creating an interval. – Nerdy Bunz Sep 16 '16 at 22:59
  • **Set the minimum displacement between location updates in meters** This line is from Official Android Documentation.Set minimum displacement between update location of User/Device and you should also check Last API called Location Manager for more info how android send updates READ this line there _third is the minimum change in distance_ – androidXP Sep 18 '16 at 21:54
  • ? I dont know how else to explain it. If you get it to work the way you intend, please update here. – Nerdy Bunz Sep 19 '16 at 02:55
0

little help who knows it can be used

    int jarak = 10;
    int interval = 5;


    LocationRequest request = new LocationRequest();
    request.setInterval(interval*1000); //update lokasi 10 detik
    request.setFastestInterval(interval*1000); //dapat update dari aplikasi lain yg lebih cepat 10 detik
    //request.setSmallestDisplacement(1); //diupdate jika berpindah 1 meter
    request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);


    FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
    int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    if(permission == PackageManager.PERMISSION_GRANTED) {



        client.requestLocationUpdates(request, new LocationCallback() {

            @Override
            public void onLocationResult(LocationResult locationResult) {
                List<Location> locationList = locationResult.getLocations();
                if (locationList.size() > 0) {
                    Location locationCurrent = locationList.get(locationList.size() - 1);


                    double latitude = locationCurrent.getLatitude();
                    double longitude = locationCurrent.getLongitude();

                    double lastlatitude = Double.parseDouble(prefs.getString("lastlatitude","0"));
                    double lastlongitude = Double.parseDouble(prefs.getString("lastlongitude","0"));

                    Location startPoint=new Location("LokasiA");
                    startPoint.setLatitude(latitude);
                    startPoint.setLongitude(longitude);

                    Location endPoint = new Location("LokasiB");
                    endPoint.setLatitude(lastlatitude);
                    endPoint.setLongitude(lastlongitude);

                    double distance = startPoint.distanceTo(endPoint);

                    Log.d(tag, "location update last " + endPoint);
                    if(distance > jarak) {
                        Log.d(tag, "location update new" + startPoint);
                        Log.d(tag, "location dest " + distance);

                        SharedPreferences.Editor editor = prefs.edit();
                        editor.putString("lastlatitude", String.valueOf(latitude));
                        editor.putString("lastlongitude", String.valueOf(longitude));
                        editor.apply();



                        Log.i("getLatitude:",String.valueOf(locationCurrent.getLatitude()) );
                        Log.i("getLongitude:",String.valueOf(locationCurrent.getLongitude()) );


                    }

                }


            }
        },null);
    }