Подтвердить что ты не робот

API местоположения Google Play Service иногда возвращает неправильное местоположение

У нас есть приложение, которое фиксирует местоположение пользователя с помощью API местоположения сервиса Google Play для каждой транзакции, такой как земля Geotag, при размещении заказа и т.д.

После захвата этих мест с мобильного телефона мы синхронизируем его с сервером и показываем его в веб-панели.

Мы заметили, что в нескольких случаях транзакция, захваченная за несколько секунд, имеет результаты поиска на разных расстояниях.


Пример:
Местонахождение пользователя будет в

Мандаур, Мадхья-Прадеш, Индия, Азия
(Широта - 24.057291, Долгота - 75.0970672, Дата захвата - 2017 -01-04 09:19:48).

Но последующие транзакции будут иметь место

Париж, что составляет 6772 км
(Широта - 48.8581074, Долгота - 2.3525187, Дата захвата - 2017-01-04 09:20:01)

>

иногда его выбор неверно указан из india, как пользователь, из gujrat, а затем извлечения из Bihar, Maharastra, Kuwait (из Индии) его действительно головной боли для индийского разработчика


Так как это происходит без вмешательства пользователя, а в пользовательском устройстве не установлены никакие приложения для определения местоположения.

Может ли кто-нибудь объяснить, почему это происходит и как мы можем избежать этих сценариев?


Примечание:
Эти местоположения транзакций фиксируются обычно в открытых полях с включенным GPS и устанавливаются в режим высокой точности

4b9b3361

Ответ 1

Местоположение, которое вы получаете от API, будет иметь точность в метрах. Вы также должны проверить, сколько лет прошло.

https://developer.android.com/reference/android/location/Location.html#getAccuracy()

https://developer.android.com/reference/android/location/Location.html#getTime()

Люди обычно отбрасывают местоположение, если точность превышает 50 или 100 м.


Почему это происходит?

Требуется некоторое время, чтобы GPS-устройство обнаружило спутники и получило сигнал. Кроме того, API попытается определить ваше местоположение на основе вашей сети. Это виды прыжков между сетью и GPS, пока GPS не предоставит некоторые точные данные.


Как этого избежать?

В своем приемнике вашего местоположения проверьте точность и подождите, пока у вас не будет лучшей точности.

Ответ 2

Для google location fused api вы можете использовать ниже код

package com.hydrometcloud.location;

import android.app.Activity;
import android.content.Context;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;


public class GoogleLocation implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        ResultCallback<LocationSettingsResult> {

    private LocationSettingsRequest mLocationSettingsRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private String TAG = "GoogleLocation";

    private Context context;
    private long UPDATE_INTERVAL = 10 * 1000;  /* 10 secs */
    private long FASTEST_INTERVAL = 2000; /* 2 sec */
    private GoogleLocationCallback googleLocationCallback;

    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    public static final int REQUEST_CHECK_SETTINGS = 0x1;

    public GoogleLocation(Context context) {
        this.context = context;
        setUpLocation();
    }

    public void setGoogleLocationCallback(GoogleLocationCallback googleLocationCallback) {
        this.googleLocationCallback = googleLocationCallback;
    }

    private void setUpLocation() {

        mGoogleApiClient = new GoogleApiClient.Builder(context.getApplicationContext())
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)        // 10 seconds, in milliseconds
                .setFastestInterval(FASTEST_INTERVAL); // 1 second, in milliseconds

        locationEnable();
    }

    public void googleClientConnect() {
        mGoogleApiClient.connect();
    }

    public void googleClientDisConnect() {
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.unregisterConnectionCallbacks(this);
            mGoogleApiClient.unregisterConnectionFailedListener(this);
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
            mGoogleApiClient = null;
        }
    }

    private void locationEnable() {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        mLocationSettingsRequest = builder.build();
        checkLocationSettings();
    }

    private void checkLocationSettings() {
        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(
                        mGoogleApiClient,
                        mLocationSettingsRequest
                );
        result.setResultCallback(this);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (location == null) {
            updateLocation();
        } else {
            handleNewLocation(location);
        }
    }

    private void handleNewLocation(Location location) {

        double currentLatitude = location.getLatitude();
        double currentLongitude = location.getLongitude();

        Log.e(TAG, "---currentLatitude--" + currentLatitude);
        Log.e(TAG, "---currentLongitude--" + currentLongitude);

        if (googleLocationCallback != null) {
            googleLocationCallback.updateLocationListner(currentLatitude, currentLongitude);
        }

    }

    public void updateLocation() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
                     /*
         * Google Play services can resolve some errors it detects.
         * If the error has a resolution, try sending an Intent to
         * start a Google Play services activity that can resolve
         * error.
         */
        if (connectionResult.hasResolution()) {
            try {
                // Start an Activity that tries to resolve the error
                connectionResult.startResolutionForResult((Activity) context, CONNECTION_FAILURE_RESOLUTION_REQUEST);
                /*
                 * Thrown if Google Play services canceled the original
                 * PendingIntent
                 */
            } catch (IntentSender.SendIntentException e) {
                // Log the error
                e.printStackTrace();
            }
        } else {
            /*
             * If no resolution is available, display a dialog to the
             * user with the error.
             */
            Log.e(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    @Override
    public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
        final Status status = locationSettingsResult.getStatus();
        switch (status.getStatusCode()) {
            case LocationSettingsStatusCodes.SUCCESS:
                Log.e(TAG, "All location settings are satisfied.");
                break;
            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                Log.e(TAG, "Location settings are not satisfied. Show the user a dialog to" +
                        "upgrade location settings ");

                try {
                    // Show the dialog by calling startResolutionForResult(), and check the result
                    // in onActivityResult().
                    status.startResolutionForResult((Activity) context, REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(TAG, "PendingIntent unable to execute request.");
                }
                break;
            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                Log.e(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
                        "not created.");
                break;
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        handleNewLocation(location);
    }

    public interface GoogleLocationCallback {
        void updateLocationListner(double latitude, double longitude);
    }
}

Теперь вы реализуете обратный вызов GoogleLocation.GoogleLocationCallback, в котором активность или фрагмент вы выбираете местоположение, и после этого пишите ниже код, по которому вы получаете местоположение или фрагмент.

googleLocation = new GoogleLocation(this);
googleLocation.setGoogleLocationCallback(this);

Ответ 3

Лучший способ решить эту проблему, фильтруя результаты. Вероятность правильного местоположения, возвращаемого службой плавких предохранителей, составляет 67%, что означает, что вы можете получить неправильное местоположение в 1/3.

Вы должны сравнить предыдущее местоположение (или более одного, чтобы быть уверенным, сохранить их в списке) с текущим, прежде чем получать местоположение. Если есть заметная разница, не используйте последнюю.

Примечание. Не сохраняйте местоположения пользователей в файле или папке, в политике конфиденциальности, просто сравните с lastKnownLocation или местоположениями, полученными в текущем сеансе.

Другая идея: если вы используете GoogleApiClient, в настоящее время я использую новый класс для плавного расположения FusedLocationProvider, вы можете проверить это.

Также, насколько я понял, они установили ограничение на выбор места в час для устройств с Android 8.0 (API уровня 26) и более поздних версий. Вы можете проверить этот документ для нового поведения.

Ответ 4

На официальном сайте разработчика Android есть страница, посвященная Стратегии местоположения для успешных приложений для Android. Вы можете прочитать больше там, поэтому, не вдаваясь в подробности, официальная документация заявляет следующее...

Вы можете ожидать, что самое последнее исправление местоположения является наиболее точным. Однако, поскольку точность определения местоположения меняется, последнее исправление не всегда является лучшим. Вы должны включить логику для выбора исправлений местоположения на основе нескольких критериев. Критерии также варьируются в зависимости от вариантов использования приложения и полевых испытаний.

Вот несколько шагов, которые вы можете предпринять для проверки правильности определения местоположения:

  • Проверьте, является ли найденное местоположение значительно более новым, чем предыдущая оценка.
  • Убедитесь, что точность, заявленная местоположением, лучше или хуже предыдущей оценки.
  • Проверьте, из какого провайдера находится новое местоположение, и определите, доверяете ли вы ему больше.

Вам также может понадобиться изучить базовый Kalman Filter в вашем приложении, чтобы поддерживать и обновлять оценку местоположения пользователя. Удачи.

Ответ 5

У меня была такая же проблема в Пуне, Индия. Устройство, используемое для тестирования, - это планшет Swipe,

Решение : я сохраняю последнюю широту и долготу и время обновления, когда следующее обновление широты и долготы вычисляет расстояние между этими двумя местоположениями, если расстояние выше 100 км, тогда оно будет не считая.

Метод, использованный для вычисления расстояния

public static double calculateDistance(double lat1,double lon1,double lat2,double lon2) {

    double theta = lon1 - lon2;
    double dist = Math.sin(deg2rad(lat1))
            * Math.sin(deg2rad(lat2))
            + Math.cos(deg2rad(lat1))
            * Math.cos(deg2rad(lat2))
            * Math.cos(deg2rad(theta));
    dist = Math.acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    return (dist);
}    

Почему это происходит

На устройстве Android есть 2 варианта для получения местоположения

  • GPS
  • Интернет

GPS (LocationManager.GPS_PROVIDER): медленное сравнение с Интернетом, но оно будет точным, чем интернет, в удаленных районах. Подключение к GPS будет медленнее и иногда трудно подключиться.

Интернет (LocationManager.NETWORK_PROVIDER): намного быстрее, чем GPS, но он менее точен, чем GPS

Если GPS недоступен, и вам нужно текущее местоположение, тогда LocationManager предоставит вам доступные данные, которые извлекаются из Интернета. (в этом случае вы также можете проверить поставщика местоположения.)

Извините за мой плохой английский, если его трудно понять, прокомментируйте

Ответ 6

Вы можете использовать это:

package com.amolood.news.manager;

/**
 * Created by nasnasa on 14/02/2017.
 */

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;


/**
 * Created by nasnasa on 14/01/2017.
 */

public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // flag for GPS status
    boolean isGPSEnabled = false;

    // flag for network status
    boolean isNetworkEnabled = false;

    // flag for GPS status
    boolean canGetLocation = false;

    Location location; // location
    double latitude; // latitude
    double longitude; // longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        getLocation();
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                // First get location from Network Provider
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

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

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     * */
    public void stopUsingGPS(){
        if(locationManager != null){
            locationManager.removeUpdates(GPSTracker.this);
        }
    }

    /**
     * Function to get latitude
     * */
    public double getLatitude(){
        if(location != null){
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }

    /**
     * Function to get longitude
     * */
    public double getLongitude(){
        if(location != null){
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/wifi enabled
     * @return boolean
     * */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }

    /**
     * Function to show settings alert dialog
     * On pressing Settings button will lauch Settings Options
     * */
    public void showSettingsAlert(){
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");

        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog,int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public void onLocationChanged(Location location) {
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

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

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

}

Подобно этому в вашей деятельности

GPSTracker gps = new GPSTracker(this);

gps.getlocation();
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();