Захват местоположения
Я проверил это, это и это источники
Я разрабатываю приложение на Android, в котором я фиксирую текущее местоположение пользователя и сохраняю на сервере мое приложение, работающее отлично,
прежде чем я расскажу вам проблему, позвольте мне объяснить, как я фиксирую местоположение
для захвата местоположения, я создал сервис, который работает каждый раз, когда пользователь входит в систему и фиксирует местоположение с помощью GPS и NETWORK
LocationService.java
public class LocationService extends Service implements LocationListener,
Runnable {
private static final int PERIOD_SECONDS = 30;
private LocationManager mgr = null;
private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
private boolean isScheduled = false;
private boolean ishaveNet = false;
//String isFrom = "";
@Override
public void onCreate() {
super.onCreate();
//Utils.printLoge(5, locService + "-->", "LocationService");
if (Utils.checkDataBase(getApplicationContext())) {
PackageManager pm = getPackageManager();
Constant.hasGps = pm.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
} else {
stopSelf();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
ishaveNet = CommonFunction.getConnectivityStatusString(getApplicationContext());
//isFrom = "extra null";
setBeforeDelay15();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
if (mgr != null)
mgr.removeUpdates(this);
/*if (executor != null)
executor.shutdown();*/
if (executor != null)
executor.shutdownNow();
//Utils.printLoge(5, "location service", "SET FALSE FLAG");
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
return (null);
}
@Override
public void onLocationChanged(Location location) {
if (!isScheduled) {
isScheduled = true;
if (executor != null)
executor.scheduleAtFixedRate(this, 0, PERIOD_SECONDS,
TimeUnit.SECONDS);
}
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void run() {
Location loc = getBestLocation();
SharedPreferences sp = getApplicationContext().getSharedPreferences("ECP", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
if (loc == null) {
//Utils.printLoge(5, locService + "error 1--->", "Got null for getBestLocation()");
editor.putBoolean(Constant.LOCATION_SAVE_LOC, false);
Utils.printLoge(5, "location service", "lOC NOT FOUND");
editor.apply();
} else {
String locService = "ECP_LOC";
Utils.printLoge(5, locService + " LOCATION_PROVIDER_LOC", "" + loc.getProvider());
editor.putBoolean(Constant.LOCATION_SAVE_LOC, true);
editor.putString(Constant.LOCATION_LAT_LOC, "" + loc.getLatitude());
editor.putString(Constant.LOCATION_LON_LOC, "" + loc.getLongitude());
String P = "";
try {
if (loc.getProvider().equalsIgnoreCase("network")) {
P = "N";
} else if (loc.getProvider().equalsIgnoreCase("gps")) {
P = "G";
}
} catch (Exception e) {
Log.e("error get provider", "error get provider");
e.printStackTrace();
}
editor.putString(Constant.LOCATION_PROVIDER_LOC, "" + P);
editor.putLong(Constant.LOCATION_SAVE_TIME_LOC, System.currentTimeMillis());
editor.apply();
}
}
private void startWork() {
if (Constant.hasGps) {
//Utils.printLoge(5, "location service", "start work");
try {
//Utils.printLoge(5, locService + " isFrom", "-->" + isFrom);
boolean isStarted = false;
if (mgr != null) {
if (Constant.hasGps) {
isStarted = true;
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
if (ishaveNet) {
isStarted = true;
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
}
}
if (!isStarted) {
try {
//Utils.printLoge(5, "location service", "insert module error log");
clsModules_Error_Log objclsError_CRMErrorLog = new clsModules_Error_Log(
"Location Services", "", "com.vcs.ecp.locservice", "get location in services", "not able to start location services because device have not GPS and not network at this time",
MyFunction.GetCurrentDate(Constant.ENTRY_DATE), "");
DBAdapter db = new DBAdapter(getApplicationContext());
db.open();
db.InsertModules_Error_Log(objclsError_CRMErrorLog);
db.close();
/***
* stop service start agian if internet is working
* */
stopSelf();
} catch (Exception e) {
e.printStackTrace();
//Utils.printLoge(5, "erro location service 2", "-->" + e.getMessage().toString());
stopSelf();
}
} else {
setDelay15();
}
} catch (Exception e) {
e.printStackTrace();
//Utils.printLoge(5, "erro location service 1", "-->" + e.getMessage().toString());
stopSelf();
}
} else {
stopSelf();
}
}
private void manageLoc() {
//Utils.printLoge(5, "location service", "manageLoc");
Intent i = new Intent(getApplicationContext(), LocationManageService.class);
getApplicationContext().startService(i);
stopSelf();
}
private Location getBestLocation() {
Location gps = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location network = mgr
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// start off by handling cases where we only have one
if (gps == null) {
return (network);
}
if (network == null) {
return (gps);
}
Location older = (gps.getTime() < network.getTime() ? gps : network);
Location newer = (gps == older ? network : gps);
if (isBetterLocation(newer, older)) {
return (newer);
} else {
// older and less accurate fixes suck
if (older.getAccuracy() <= newer.getAccuracy()) {
return (newer);
}
// if older is within error radius of newer, assume
// not moving and go with older (since has better
// accuracy, else would have been caught by previous
// condition)
// ideally, this would really be "if the odds of
// the older being within the error radius of the
// newer are higher than 50%", taking into account
// the older one's accuracy as well -- the
// implementation
// of this is left as an exercise for the reader
if (newer.distanceTo(older) < newer.getAccuracy()) {
return (older);
}
// if all else fails, choose the newer one -- the device
// is probably moving, and so we are better off with the
// newer fix, even if less accurate
return (newer);
}
}
private static final int TWO_MINUTES = 1000 * 60 * 2;
/**
* Determines whether one Location reading is better than the current Location fix
*
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
private boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/**
* Checks whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
/*public void saveFlagStop(boolean isStartManage) {
Utils.printLoge(5, "location service", "STOP lOC");
if (isStartManage == true) {
manageLoc();
}
stopSelf();
}*/
}
Теперь проблема в том, что иногда это дает мне неправильное местоположение, как будто пользователь, использующий мое приложение, находится в ИНДИИ, но GPS дает мне местоположение ИРАНА. Таким же образом, пользователь использует мое приложение в одном из штатов Индии, как TELANGANA, но GPS дает мне местоположение BIHAR.
Я попытался выяснить эту проблему, и я знаю, что это зависит от источников сервера, таких как GPS, WIFI, сотовые данные и устройства H/W
это объясняется в этом https://productforums.google.com/forum/#!topic/maps/otb4M1PilHw;context-place=topicsearchin/maps/category
но все же я хочу правильное решение этой проблемы или это ошибка?