Android位置不正确 [英] Android location is inaccurate

查看:71
本文介绍了Android位置不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取当前用户的位置.我试图重构代码以获得更好的结果,但我一直在获得关于准确性的荒谬位置,它在900-600米之间.

I am trying to get the current user's location. I have tried to refactor my code to get better results but I just keep getting ridiculous locations in regard to the accuracy, it is between 900-600 meters.

如何获得更好的结果,以使其精确到50m以内?

How can I get a better result, so as to force it to an accuracy within 50m?

这是我的代码:

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

注意:我将重点放在静态位置,例如不要动,因为它可能有助于答案.

Note: I am putting emphasis on static location, e.g. not moving because it may help with the answers.

推荐答案

要获取准确的位置,您需要考虑两个因素:

There are two factors you need to consider to obtain an accurate location:

  1. 代码,例如

  1. The code, eg

  • 使用正确的位置提供商(GPS与网络)
  • 在您的应用中拥有正确的权限

设备

  • 具有适当的传感器(并非所有的Android设备都具有GPS,Wifi或电话)
  • 启用了适当的传感器(例如,用户尚未关闭GPS)
  • 已安装正确的Google服务(由制造商决定)

这些将在下面讨论.

代码

确保已遵循 Android Developer (感谢比尔·加里)

但是请记住,只有在设备本身具有必需的硬件和配置时,该代码才有效-参见下文.

But remember that the code will work only if the device itself has the requisite HW and configuration - see below.

设备

要了解您的位置修复出了什么问题,真的有助于了解您的设备如何定位自身.位置是通过几种技术获得的:

To understand what is going wrong with your location fix, it really helps to understand how your device locates itself. Location is obtained by several technologies:

  1. GPS芯片组

  1. GPS chipset

  • 最准确
  • 需要在窗户外面或窗户附近
  • 要求GPS芯片组处于打开状态

在WiFi上可见的MAC(通过查询中央数据库(例如Google的数据库)

MACs visible on WiFi (by querying a central DB such as Google's)

  • 通常非常准确(10-100m,具体取决于存在的WiFi数量以及是否曾经见过)
  • 挺快的
  • 要求打开wifi
  • 要求与Internet的数据连接处于打开状态(不一定在WiFi上)
  • 要求在设备上安装Google服务(某些便宜的设备可能没有此功能)

您正在使用的手机天线杆的位置(网络提供商)

The location of the cell-phone mast you are using (Network Provider)

  • 精确到几百米到几千米
  • 经常立即
  • 要求打开电话

当您要求位置定位(不包括最后一个缓存的位置)时,一个好的GPS定位提供商实际上所关注的不仅仅是GPS:

When you ask for a location fix (excluding the last, cached one), a good GPS location provider actually looks at a lot more than just GPS:

  1. 如果启用了GPS芯片组,它将开始GPS跟踪

  1. It starts GPS tracking if the GPS chipset is enabled

  • 10秒钟后,只有获得修复后,LocationProvider才会返回GPS位置
  • 稍后,设备会将设备的GPS位置以及可见的WiFi MAC/名称发送给Google,然后Google会将其合并到其WiFi AP的数据库中

如果启用了WiFi,它将开始对Wifi环境进行扫描

It starts a scan of the Wifi environment, if WiFi is enabled

  • 几秒钟后,WiFi扫描完成后,它将结果发送到Google的服务器
  • 大约一秒钟后,服务器返回定位信息

通常,您会在Google Maps上看到这些效果,例如:启动时,您会看到Network Provider的一个很大的大概位置(蜂窝塔),几秒钟后,它会放大一个更大程度的区域精确度(WiFi),最后您可能会获得GPS修复.

Often you can see these effects on Google Maps, for example: when you start it you see a large approximate location (cell tower) from the Network Provider, a few seconds later it zooms in on an area with a greater degree of accuracy (WiFi), and finally you may get a GPS fix.

总是值得的:

  • Using the correct/generic approach to picking a LocationProvider (rather than hardcoding)
  • Checking the relevant HW sensors are present and enabled
  • Checking that Google Maps is locating your device as you expect (and if your device does not come with Google Maps, then you don't have Google Services and likely you have a very basic GPS-only provider).
  • If you suspect the GPS chipset, use a GPS app to get a detailed view of what it is doing and capable of, eg https://play.google.com/store/apps/details?id=com.eclipsim.gpsstatus2&hl=en

编辑

从获得的基本结果来看,您似乎只有网络提供商提供的结果.所以,做:

From the basic results you're getting, you seem to have only results from the Network Provider. So, do:

  • 检查GPS是否已打开
  • 您的GPS接收器能否获得修复(例如,使用GPS应用进行调试)和
  • (可能通过logcat)将一些调试放入代码中,这样您就可以看到为什么 isBetterLocation()方法决定一个位置而不是另一个位置.
  • Check whether GPS is on,
  • Whether your GPS receiver can get a fix (eg using a GPS app for debugging) and
  • Put some debug into your code (probably via logcat) so you can see why the isBetterLocation() method decides on one location rather than the other.

这篇关于Android位置不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆