我正在尝试获取当前用户的位置。我试图重构我的代码以获得更好的结果,但我只是在准确性方面保持荒谬的位置,它在900-600米之间。
如何才能获得更好的结果,以便将其强制到50米以内?
这是我的代码:
package com.agam.mapslocation;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
public class MapsActivity extends Activity {
private static final int ONE_MINUTE = 1000 * 60 * 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
final LocationManager locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
final EditText et = (EditText) findViewById(R.id.editText1);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location l) {
// Called when a new location is found by the network location
// provider.
Location gps = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location net = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Location bestLocation = null;
bestLocation = isBetterLocation(gps, net);
bestLocation = isBetterLocation(bestLocation, l);
if(bestLocation!=null)
displayLocation(et, bestLocation);
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
if (provider.equals(LocationManager.GPS_PROVIDER)) {
et.setText("GPS ON!");
}
}
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location
// updates
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, locationListener);
}
public static void displayLocation(View v, Location l) {
((EditText) v).setText(String.format(
"Long:%s,\nLat:%s,\nAccu:%s,\nTime ago:%s,\nProvider:%s",
l.getLongitude(), l.getLatitude(), l.getAccuracy(),
new java.util.Date().getTime() - l.getTime(), l.getProvider()));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_maps, menu);
return true;
}
/**
* 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
*/
protected Location isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return location;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > ONE_MINUTE;
boolean isSignificantlyOlder = timeDelta < -ONE_MINUTE;
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 location;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return currentBestLocation;
}
// 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 location;
} else if (isNewer && !isLessAccurate) {
return location;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return location;
}
return currentBestLocation;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}
注意:我强调静态位置,例如不动,因为它可能有助于答案。
答案 0 :(得分:3)
要获得准确的位置,您需要考虑两个因素:
代码,例如
设备
这些将在下面讨论。
<强>代码强>
确保您已遵循Android Developer(感谢Bill Gary)
的指导但请记住,只有当设备本身具有必要的硬件和配置时,代码才会起作用 - 见下文。
设备
要了解您的位置修复程序出了什么问题,确实有助于了解您的设备如何定位自己。位置是通过几种技术获得的:
GPS芯片组
在WiFi上可见MAC(通过查询Google等中央数据库)
您正在使用的手机桅杆的位置(网络提供商)
当你要求定位(不包括最后一个,缓存的定位)时,一个优秀的GPS定位提供商实际上看起来不仅仅是GPS:
如果启用了GPS芯片组,它将启动GPS跟踪
如果启用WiFi,它将开始扫描Wifi环境
通常,您可以在Google地图上看到这些效果,例如:当您启动它时,您会看到来自网络提供商的大型大致位置(手机信号塔),几秒钟后它会放大更大程度的精度(WiFi),最后你可以获得GPS修复。
总值得:
修改强>
从您获得的基本结果来看,您似乎只有网络提供商的结果。所以,做:
答案 1 :(得分:0)
您应该尽快将locationListeners设置为所有可用的位置提供程序并等待。设置监听器要求提供者立即为您提供所有数据(minTime = 0,minDistance = 0)。使用getLastKnownLocation作为第一个位置近似值。 在此期间,您将开始从不同的提供商处获取一些位置数据。您应该手动选择最适合您的情况(我猜是最精确的)。尽可能长时间等待(您等待的位置值越多,您可能会获得)。 当等待时间结束时,请选择您最好的位置并开始使用它。如果系统能够为您提供更好的价值,您可以继续收听位置更新并改进位置估算。