Android位置不准确
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android位置不准确相关的知识,希望对你有一定的参考价值。
我想获取当前用户的位置。我试图重构我的代码以获得更好的结果,但我只是在准确性方面保持荒谬的位置,它在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,
Lat:%s,
Accu:%s,
Time ago:%s,
Provider:%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);
}
}
注意:我强调静态位置,例如不动,因为它可能有助于答案。
要获得准确的位置,您需要考虑两个因素:
- 代码,例如 使用正确的位置提供商(GPS与网络) 在您的应用中拥有正确的权限
- 装置 拥有合适的传感器(并非所有Android设备都有GPS,Wifi或电话) 启用适当的传感器(例如,用户未关闭GPS) 安装了正确的Google服务(制造商决定)
这些将在下面讨论。
码
确保你遵循了Android Developer的指导(谢谢Bill Gary)
但请记住,只有当设备本身具有必要的硬件和配置时,代码才会起作用 - 见下文。
设备
要了解您的位置修复程序出了什么问题,了解设备如何定位本身确实很有帮助。位置是通过几种技术获得的:
- GPS芯片组 最准确的 慢 需要在窗户外面或附近 需要GPS芯片组打开
- WiFi上可见MAC(通过查询Google等中央数据库) 通常令人惊讶的准确(10-100米取决于存在多少WiF,以及之前是否曾见过) 蛮快 需要wifi才能打开 需要连接到Internet的数据连接(不一定是在WiFi上) 需要在设备上安装Google服务(某些便宜的设备可能没有此功能)
- 您正在使用的手机桅杆的位置(网络提供商) 准确到几百米到几公里 经常立即 需要打电话
当你要求一个位置修复(不包括最后一个,缓存的),一个好的GPS位置提供商实际上看起来不仅仅是GPS:
- 如果启用GPS芯片组,它将启动GPS跟踪 10秒后,只有在获得修复后,LocationProvider才会返回GPS位置 稍后该设备会将设备的GPS位置以及可见的WiFi MAC /名称发送给Google,Google会将其整合到他们的WiFi AP数据库中
- 如果启用了WiFi,它将开始扫描Wifi环境 几秒钟后,当WiFi扫描完成后,它会将结果发送到Google的服务器 大约一秒钟后,服务器返回一个位置修复程序
通常,您可以在Google地图上看到这些效果,例如:当您启动它时,您会看到来自网络提供商的大型大致位置(手机信号塔),几秒钟后它会放大一个具有更高精确度的区域(WiFi) ),最后你可能得到GPS修复。
它始终值得:
- 使用picking a LocationProvider的正确/通用方法(而不是硬编码)
- 检查相关的HW传感器存在并启用
- 检查Google地图是否按预期定位您的设备(如果您的设备未附带Google地图,那么您没有Google服务,而且您可能拥有一个非常基本的GPS专享提供商)。
- 如果您怀疑GPS芯片组,请使用GPS应用程序详细了解它的功能和能力,例如https://play.google.com/store/apps/details?id=com.eclipsim.gpsstatus2&hl=en
编辑
从您获得的基本结果来看,您似乎只有网络提供商的结果。所以,做:
- 检查GPS是否打开,
- 您的GPS接收器是否可以修复(例如使用GPS应用程序进行调试)和
- 将一些调试放入您的代码中(可能通过logcat),这样您就可以看到为什么isBetterLocation()方法决定在一个位置而不是另一个位置。
您应该尽快将locationListeners设置为所有可用的位置提供程序并等待。设置监听器要求提供者立即为您提供所有数据(minTime = 0,minDistance = 0)。使用getLastKnownLocation作为第一个位置近似值。在此期间,您将开始从不同的提供商处获取一些位置数据。您应该手动选择最适合您的情况(我猜是最精确的)。尽可能长时间等待(您等待的位置值越多,您可能会获得)。当等待时间结束时,请选择您最好的位置并开始使用它。如果系统能够为您提供更好的价值,您可以继续侦听位置更新并改进位置估算。
以上是关于Android位置不准确的主要内容,如果未能解决你的问题,请参考以下文章
如何在不在 android 的 Activity 上添加地图片段的情况下获取我的位置?
Android 逆向Android 进程注入工具开发 ( Visual Studio 开发 Android NDK 应用 | Visual Studio 中 SDK 和 NDK 安装位置 )(代码片段