2017-02-13 4 views
32

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

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

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


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

Mandsaur, Мадхья-Прадеш, Индия, Азия
(широта - 24,057291, Долгота - 75,0970672, Захваченные дата - 2017-01- 04 09:19:48).

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

Париж, который 6772 км
(широта - 48,8581074, Долгота - 2,3525187, Захваченная дату - 2017-01-04 09:20:01)


иногда его выборки неправильно заявил о индии как пользователь находится в Гуджарате, то местоположение выборки Бихар, Махараштра, Кувейт (из Индии) его действительно головная боль для индийского разработчика


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

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


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

+0

Вы используете Google слиты апи? Если да, то какая версия? – Umar

+0

Да, мы используем плавный API ** com.google.android.gms: play-services-location: 10.0.1 ** –

+0

Я думаю, что тот же вопрос задан [здесь] (http://stackoverflow.com/questions/35095177/google-play-services-location-api-when-give-wrong-location) о неточности Карт Google. – noogui

ответ

1

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

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

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

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

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

на андроид устройстве есть 2 варианта, чтобы получить место

  • GPS
  • Интернет

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

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

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

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

8

место, которое вы получаете от 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 не предоставит некоторые точные данные.


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

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

+0

Мы используем местоположение для записей таймера с помощью приемника местоположения.Наши пользователи не согласятся ждать, поэтому мы ничего не записываем, если точность плоха. Тем не менее, Google иногда поставляет места, которые имеют ОГРОМНУЮ разницу (> 10 км) к реальности, и маркирует их как точную. У нас есть некоторые «теории заговора» о перемещенных маршрутизаторах беспроводной локальной сети и т. Д. Если я сам должен обрабатывать точность, то материал из Google не имеет никакого смысла. –

2

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

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

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

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

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

4

Для определения местоположения Google плавленого 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); 
+0

Ищет ответ, взятый из достоверных и/или официальных источников. ваш ответ содержит это или нет? –

+0

Я использовал google fused location api и используя это, я получаю точное местоположение, поэтому здесь я дал свой собственный класс местоположения google ... так что может быть он вам полезен. –

2

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

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

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

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

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

0

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

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(); 
Смежные вопросы