Android GPS 查询位置数据不正确
Posted
技术标签:
【中文标题】Android GPS 查询位置数据不正确【英文标题】:Android GPS incorrect location data on query 【发布时间】:2014-07-20 16:42:10 【问题描述】:我没有为此使用模拟位置...事实上,代码在上周运行良好。
我有一个应用程序,它收集 GPS 数据并使用应用程序本身生成的 X、Y 坐标输出谷歌地图链接。我不是 100% 确定为什么它没有按应有的方式工作,但是当我请求应用程序根据手机提供的 GPS 位置创建谷歌地图链接时,它告诉我我距离我的点 5 - 6 个街区起源(我当时实际在哪里)不是我想要它做的事情
已知:
我已设置适当的权限 上周所有代码都运行良好这是收集 GPS 信息的代码:
Toast.makeText(context, "Gathering GPS Data...", Toast.LENGTH_SHORT).show();
gps = new gpsTracker(Settings.this);
if(gps.canGetLocation())
try
gps.getLocation();
lon = gps.getLongitude();
lat = gps.getLatitude();
Toast.makeText(getApplicationContext(), "Your location is - \nlat: " + lat + "\nlon: " + lon, Toast.LENGTH_LONG).show();
catch(Exception e)
else
gps.showSettingsAlert();
以上所有课程均来自:
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;
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 不是标准的 android 类。没有它的代码,就无法知道出了什么问题。我的猜测是,您要么使用过时的位置,要么使用网络提供商,在那里您没有准确的锁定,但它纯粹是没有代码的猜测。 我会添加那个新的类/位置监听器......对不起,那是我的derp。 @GabeSechan - 刚刚添加。 所以关于我的猜测。您正在调用 getLastKnownLocation,因此它可能会返回一个陈旧的位置,该位置可能很容易在几个街区之外 - 或者来自网络提供商的位置在锁定时可能会偏离几个街区。 @GabeSechan 所以,摆脱它,它应该再次工作? 【参考方案1】:根据指定[4-5 块的差异],您可能仅从networkProvider
获得location
。
有了问题中提到的这个gpsTracker
代码,
需要进行一些修改,而不是按原样使用代码:
1.
有 2 个if
循环验证location
的来源是否启用并且没有'else
':
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();
这意味着当您可以从两个来源获得location
时,应用程序将完成两倍的工作。此外,获得的location
的来源始终是模棱两可的。
当您只需要近似的 location
时,这很好,它主要不应该为空。
如果你只想使用这个类来获取location
,请尝试根据需求构造if-else
,并确保在获取location
时不会重复。例如。如果GPS
的偏好更高,则适用于您的情况,将if
移到上面,并将网络条件与else
类似:
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();
else 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();
根据您的要求,我建议删除网络提供商部分并仅从 GPS 获取location
,尤其是在视线不成问题的情况下。
当您的代码工作正常时,它必须从 GPS 获取位置并将其设置在对象中。但是因为有两个“if
”而没有“else
”,所以你永远不知道得到的location
是来自网络还是来自GPS——你可以在canGetLocation()
的条件下查看location.getProvider()
2. 此外,您可以记录消息或提示针对某个特定来源的某些操作...例如: 在这部分:
if (!isGPSEnabled && !isNetworkEnabled)
// no network provider is enabled
只需将其分成两个不同的if
(s) 并相应地编码。到目前为止,这里没有任何反应,因此除非您从外部检查,否则您不会知道两者是否都被禁用。
建议:试试 LocationClient which uses GooglePlayServices 换成 Retrieving Current Location 。我发现它更可靠和有用。检查这个Fused Location Provider example,根据你的要求设置LocationRequest object是关键。
另一个更新:刚刚遇到:useful ques on stack overflow - Good way of getting the users location
任何查找此问题/答案的人的更新
关于LocationClient的建议;
在com.google.android.gms.location
下不再找到LocationClient,参考:Android play services 6.5: LocationClient is missing
【讨论】:
非常感谢。我明白发生了什么。我觉得自己没有解决这个问题有点傻,但我很高兴我能成功! 很好,你已经成功了,这很重要。我们有时会错过一些东西,这就是为什么会有SO【参考方案2】:您应该查看http://developer.android.com/guide/topics/location/strategies.html。有一些很好的策略可以在此页面上获取准确的位置。这是我从网站上获取的一些示例代码:
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
*/
protected 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);
【讨论】:
以上是关于Android GPS 查询位置数据不正确的主要内容,如果未能解决你的问题,请参考以下文章