Location App on Android

I have problem with stable reading on the start from this application. In first minute or so reading get very jumpy. Between 10-100 meters’ difference even in distance. I heard it is common error in location applications especially one using GPS. Can I prevent this somehow with pause on reading on this start? With some fancy text like “Calculating your location” or something like that for first 10-20 seconds?
And if yes. Where I should implement this pause? So it will get readings and stabilized them but don’t mess up calculations? Or there is any other way to prevent messy starting reading? Ofc any other suggestion on upgrade of current also very welcome:)

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {

    String addressString = "No address found";
    String latLongString = "Your Current Position is: ";

    double latitude = 10;
    double longitude = 10;
    double sLatitude;
    double sLongitude;
    double eLatitude;
    double eLongitude;
    double distance = 10;
    double el1 = 0;
    double el2 = 0;
    double counter = 2;

    TextView myLocationText;
    TextView myLatitude;
    TextView myLongitude;
    TextView myAddress;
    TextView startingLatitude;
    TextView startingLongitude;
    TextView endingLatitude;
    TextView endingLongitude;
    TextView myDistance;
    TextView myLogOut;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LocationManager locationManager;
        String context = Context.LOCATION_SERVICE;
        locationManager = (LocationManager) getSystemService(context);

        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(true);
        criteria.setPowerRequirement(Criteria.POWER_LOW);

        String provider = locationManager.getBestProvider(criteria, true);
        Location location = locationManager.getLastKnownLocation(provider);

        myLatitude = (TextView) findViewById(R.id.Latitude);
        myLongitude = (TextView) findViewById(R.id.Longitude);
        myLocationText = (TextView) findViewById(R.id.myLocationText);
        myAddress = (TextView) findViewById(R.id.Address);
        startingLatitude = (TextView) findViewById(R.id.startingLatitude);
        startingLongitude = (TextView) findViewById(R.id.startingLongitude);
        endingLatitude = (TextView) findViewById(R.id.endingLatitude);
        endingLongitude = (TextView) findViewById(R.id.endingLongitude);
        myDistance = (TextView) findViewById(R.id.distance);
        myLogOut = (TextView) findViewById(R.id.logOut);

        if (location != null) {
            sLatitude = location.getLatitude();
            sLongitude = location.getLongitude();

        }

        updateWithNewLocation(location);

        locationManager.requestLocationUpdates(provider, 1000, 2,
                locationListener);

    }

    private final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            updateWithNewLocation(location);
        }

        @Override
        public void onProviderDisabled(String provider) {
            updateWithNewLocation(null);
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    private void updateWithNewLocation(Location location) {

        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();

            eLatitude = location.getLatitude();
            eLongitude = location.getLongitude();
            distance = distance(sLatitude, eLatitude, sLongitude, eLongitude,
                    el1, el2);

            Geocoder gc = new Geocoder(this, Locale.getDefault());
            try {

                List<Address> addresses = gc.getFromLocation(latitude,
                        longitude, 1);
                StringBuilder sb = new StringBuilder();
                if (addresses.size() > 0) {
                    Address address = addresses.get(0);

                    for (int i = 0; i < address.getMaxAddressLineIndex(); i++)
                        sb.append(address.getAddressLine(i)).append("\n");
                    sb.append(address.getLocality()).append("\n");
                    sb.append(address.getPostalCode()).append("\n");
                    sb.append(address.getCountryName());
                }
                addressString = sb.toString();
            } catch (IOException e) {
            }
        } else {
            latLongString = "No location found";
        }

        myLocationText.setText(latLongString);
        myLatitude.setText("Latitude: " + latitude);
        myLongitude.setText("Longitude: " + longitude);
        myAddress.setText(addressString);
        startingLatitude.setText("Starting latitude: " + sLatitude);
        startingLongitude.setText("Starting longitude: " + sLongitude);
        endingLatitude.setText("Last latitude: " + eLatitude);
        endingLongitude.setText("Last longitude: " + eLongitude);
        myDistance.setText("Your distance to starting point: " + distance);

    }

    public static double distance(double lat1, double lat2, double lon1,
            double lon2, double el1, double el2) {

        final int R = 6371; // Radius of the earth

        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1))
                * Math.cos(Math.toRadians(lat2)) * Math.sin(lonDistance / 2)
                * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = R * c * 1000; // convert to meters

        double height = el1 - el2;

        distance = Math.pow(distance, 2) + Math.pow(height, 2);
        return Math.sqrt(distance);
    }

}

1 answer

  • answered 2017-10-11 10:32 Moshe Edri

    yeah , you can use the GoogleApiClient to get user location and it will take care of everything for you , it's better practise in android to use GoogleApiClient for location because it uses last known location as it's starting point and it share the location data that it collect between all the app on the device

    here is some basic code logic to get you started

    public class MainActiviy extend Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    
             @Override
                protected void onStart() {
                    super.onStart();
                        mGoogleApiClient.connect();
                }
    
              @Override
                protected void onStop() {
                    if(mGoogleApiClient.isConnected()){
                        mGoogleApiClient.disconnect();
                    }
            }
    
            @Override
                public void onConnected(@Nullable Bundle bundle) {
                    LocationRequest mLocationRequest = LocationRequest.create();
                    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                    mLocationRequest.setInterval(1000);//REQUEST_LOCATION_INTERVAL 
                    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    
    
    
                        if (ActivityCompat.shouldShowRequestPermissionRationale(
                                this,
                                Manifest.permission.ACCESS_FINE_LOCATION)) {
    
                            AlertDialog.Builder builder = new AlertDialog.Builder(this);
                            builder.setMessage(R.string.permission_prompt_location);
                            builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    ActivityCompat.requestPermissions(
                                           MainActivity.this,
                                            new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                                    Manifest.permission.ACCESS_COARSE_LOCATION},
                                            REQUEST_LOCATION);
                                }
                            });
                            builder.create().show();
                        } else {
                            ActivityCompat.requestPermissions(
                                    this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                            Manifest.permission.ACCESS_COARSE_LOCATION},
                                    REQUEST_LOCATION);
                        }
    
    
    
                        return;
                    }
                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    
                }
    
         @Override
            public void onRequestPermissionsResult(
                    int requestCode,
                    String[] permissions,
                    int[] grantResults) {
              if(mGoogleApiClient.isConnected()){
                  mGoogleApiClient.disconnect();
              }
    
                mGoogleApiClient.connect();
    
    
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
            }
    
    
    
    
     @Override
        public void onLocationChanged(Location location) {
    updateWithNewLocation( location);
    }
    
    }