javaandroidgpslocationlocation-services

Jumping gps location in android 10


I use location service in my navigation app. The service get location per second. But jumping gps location is like this photo:

enter image description here

In the service used the GoogleApiClient and LocationListener for get best last location. Also used broadcast for send result to app. and my location service is:

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {


    private static final String TAG = LocationFinder.class.getSimpleName();
    private Location location;
    private GoogleApiClient googleApiClient;
    private LocationRequest locationRequest;
    private static final long UPDATE_INTERVAL = 1000, FASTEST_INTERVAL = 1000;
    private Context context;
    // Send Data to View with BroadCast
    static final public String GDS_RESULT = "AE_Find_Location";
    static final public String GDS_SPEED = "Service_SPD";
    static final public String GDS_LAT = "Service_lat";
    static final public String GDS_LON = "Service_lon";
    static final public String GDS_BEARING = "Service_bearing";
    private LocalBroadcastManager broadcaster;
    private int SEND_LOCATION_TIMER = 30000;
    public static final int REQUEST_CHECK_SETTINGS = 100;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();

        // we build google api client
        googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)

                .addOnConnectionFailedListener(this).build();
        broadcaster = LocalBroadcastManager.getInstance(this);

    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (googleApiClient != null)
            googleApiClient.connect();
        startSendData();

        return START_STICKY;

    }


    private ArrayList<Location> locations = new ArrayList<>();
    private ConcurrentLinkedQueue<Coordinate> queue = new ConcurrentLinkedQueue<>();
    private Timer timer;
    private TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (location == null) return;

                    sendResult(location);

                }
            }).start();
        }
    };

    public void startSendData() {

        if (timer != null) {
            return;
        }
        timer = new Timer();
        timer.scheduleAtFixedRate(timerTask, 0, 1000);
    }

    public void stopSendData() {
        if (timer == null) return;
        timer.cancel();
        timer = null;
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onConnected(Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        Log.i(TAG, "onResult: connected");
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true);

        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(
                        googleApiClient,
                        builder.build()
                );

        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();

                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // NO need to show the dialog;

                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            status.startResolutionForResult(MyApplication.currentActivity, REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            //failed to show dialog

                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are unavailable so not possible to show any dialog now

                        break;
                }
            }
        });

        // Permissions ok, we get last location
        location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);

        startLocationUpdates();
    }

    private void startLocationUpdates() {
        locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(UPDATE_INTERVAL);
        locationRequest.setFastestInterval(FASTEST_INTERVAL);

        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        }

        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            this.location = location;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // stop location updates
        if (googleApiClient != null && googleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
            googleApiClient.disconnect();
        }
        stopSendData();

    }

    public void sendResult(Location location) {
        try {
            if (location == null) return;

            String lat = HelperNumber.convertNumber(new DecimalFormat("##.#####").format(location.getLatitude()));
            String lng = HelperNumber.convertNumber(new DecimalFormat("##.#####").format(location.getLongitude()));

            Intent intent = new Intent(GDS_RESULT);
            intent.putExtra(GDS_SPEED, location.getSpeed());
            intent.putExtra(GDS_LAT, Double.valueOf(lat));
            intent.putExtra(GDS_LON, Double.valueOf(lng));
            intent.putExtra(GDS_BEARING, location.getBearing());
            broadcaster.sendBroadcast(intent);

            if (MyApplication.prefManager.getApiRequestTime() + SEND_LOCATION_TIMER > Calendar.getInstance().getTimeInMillis())
                return;
            MyApplication.prefManager.setApiRequestTime(Calendar.getInstance().getTimeInMillis());


        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}

Thanks about your help.


Solution

  • The best way to normalize jumping gps in smartphone is remove locations that the low accuracy. Also the location accuracy is low on low speeds. I hope this way useful to resolve this problem.