应用程序获取错误位置,直到打开内置的谷歌地图应用程序

12

我开发了一个应用程序,用于查找设备的当前位置。我使用了 Fused Location API 来获取当前位置。

我遇到了一个非常奇怪的问题,在一些设备上,我无法获取准确的当前位置,直到我打开内置的 Google 地图,一旦我打开 Google 地图然后返回我的应用程序,此时应用程序会返回精确的位置。

以下是我的位置请求。

mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT); // 10 meters

有人可以告诉我错在哪里吗?非常感谢您的帮助。


你的位置请求是什么? - Eugen Pechanec
3
加油,你已经有了33,000分。我应该猜测具体数值吗?请把它放在问题里而不是评论中。手机设置中启用了高精度定位吗?你收到了多少个位置更新?你测试过哪些设备?使用的GMS库版本是多少?任何你能想到的都有帮助。 - Eugen Pechanec
2
已经是会员5年了,仍然在评论中发布代码。哦,天啊... - 2Dee
你用了哪些设备? - bendaf
4个回答

4

过去我们在Waze和其他项目中使用了FusedLocation技术,但是遇到了很多问题。API已经损坏,有些设备无法正确地执行该技术。融合了许多信息的Activity识别不起作用,无法正确地识别人员。因此我们最终决定切换回定位管理器API。

以下是代码片段:

初始化定位管理器并在不同的线程上开始请求更新。我个人为每个提供者注册单独的监听器。

if (mLocationManager == null) {
        LOGGER.info("Location track,start called first time. Creating Location Manager");
        mLocationManager = (LocationManager) mContextWeakReference.get()
                .getSystemService(Context.LOCATION_SERVICE);

        mLocationHandlerThread
                = new HandlerThread("LocationThread", Thread.NORM_PRIORITY);
        mLocationHandlerThread.start();
        // Now get the Looper from the HandlerThread
        // NOTE: This call will block until the HandlerThread gets control and initializes its Looper
        Looper looper = mLocationHandlerThread.getLooper();
        Location networkLastKnownLocation = null;
        Location gpsLastKnownLocation = null;
        mGpsLocationListener = new GpsLocationListener();
        mNetworkLocationListener = new NetworkLocationListener();

        // Register the listener with the Location Manager to receive location updates
        if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER)) {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                    LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
                    mGpsLocationListener,
                    looper);

            gpsLastKnownLocation = mLocationManager
                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        } else {
            setGpsProviderAvailable(false);
        }
        if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER)) {
            networkLastKnownLocation = mLocationManager
                    .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
                    LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
                    mNetworkLocationListener,
                    looper);
        }

        setLastKnownLocationDifferentProviders(gpsLastKnownLocation,
                networkLastKnownLocation);

    }

听众包括:

public class GpsLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location location) {
        LOGGER.info("Location track ,onLocationChanged location={}", location);
        switch (location.getProvider()) {
            case LocationManager.GPS_PROVIDER:
                if (mLocationManager != null) {
                    mLocationManager.removeUpdates(mNetworkLocationListener);
                }
                break;
        }
        setLastKnownLocation(location);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
    }

    @Override
    public void onProviderEnabled(String provider) {
        LOGGER.info("onProviderEnabled: " + provider);
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            setGpsProviderAvailable(true);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        LOGGER.info("onProviderDisabled: " + provider);
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            setGpsProviderAvailable(false);
        }
    }
}

public class NetworkLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location location) {
        LOGGER.info("Location track ,onLocationChanged location={}", location);
        switch (location.getProvider()) {
            case LocationManager.NETWORK_PROVIDER:
                setLastKnownLocation(location);
                break;
        }
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
    }

    @Override
    public void onProviderEnabled(String provider) {
        LOGGER.info("onProviderEnabled: " + provider);
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            setGpsProviderAvailable(true);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        LOGGER.info("onProviderDisabled: " + provider);
        if (provider.equals(LocationManager.GPS_PROVIDER)) {
            setGpsProviderAvailable(false);
        }
    }
}

不要忘记注销并停止所有线程 :)


我是否总是需要为此侦听器创建一个单独的线程?我的用户走得相对缓慢,我不需要高频率更新;此外,位置仅被推送以进行进一步处理:没有任何东西会卡在UI线程上。 - Alex Cohn
另一个问题:有一些智慧可以过滤掉“错误”的位置更新。 - Alex Cohn
1
  1. 不需要为此单独创建线程。您可以使用同一UI线程来获取onLocationChange。
  2. 这是完全不同的故事 :) 需要编写一本书来筛选出错误位置。
- Yonatan Levin

0

我不确定这件事,但在我上次看到类似的情况时,那部手机没有专用GPS。它只有a-GPS。

玩了很长时间之后,我意识到这就是我没有获得准确位置的原因。但打开地图后,位置出奇的准确。即使手机没有专用GPS,Google在地图中进行了许多其他操作来获取准确的位置。只需检查设备及其硬件规格。


0

在创建LocationRequest时,您必须将setPriority()设置为PRIORITY_NO_POWER。

PRIORITY_NO_POWER意味着除非手机中的其他应用程序请求位置并接收到位置信息,否则您的应用程序将永远不会获取任何位置信息。请在LocationRequest中了解更多信息。


你展示问题如何可靠地复现,而不是如何修复它。 - Alex Cohn

-1
你们在测试 Marshmallow 及以上版本的设备吗? 在 Lollipop 以上的设备中,您必须在运行时请求位置权限。请参考此链接 http://developer.android.com/training/permissions/requesting.html。因此,您可能没有位置权限,因此它不会返回准确的位置,但是当您启动具有 Gps 权限的地图应用程序时,将在 Google play service 中更新您的位置。因此,由于位置最终是从 Google play service 获取的,因此也会开始显示正确的位置。

那不正确。该应用程序被标记为针对棒棒糖版本,因此即使在棉花糖版本上,权限仍然按照旧的方式工作。此外,位置更新确实到达,只是比使用Maps时精度较低。另外,如果我从融合切换到GPS位置提供程序,则更新可以正常工作。 - Alex Cohn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接