Android:requestLocationUpdates最多每45秒更新一次位置

时间:2012-02-29 22:20:11

标签: android location

背景

我正在编写一个Android应用程序,其主要功能是跟踪用户的位置,并在用户接近某个点时发出警报。因此,我需要定期更新用户的位置,并且当用户接近目标时,这些间隔应该变小。因此,当用户位于目标1公里范围内时,我希望每20秒更新一次该位置,依此类推,直到用户到达。

问题

当我对其进行测试时(provider = LocationManager.NETWORK_PROVIDER),使用任何requestLocationUpdates(provider, minTime, minDistance, locationListener)调用minTime < 45000minTime = 45000具有相同的效果,即我获得的间隔为< em>完全 45秒 我知道最小时间参数只是一个“提示”,但它不是我的应用程序提示。我得到指定间隔的更新,直到该间隔超过45秒。似乎位置更新之间的最短时间为45秒,硬编码到Android中,但这有点奇怪。另外我以前从未听说过这个问题,而且我无法在Stackoverflow上找到它。

由于我无法获得频繁的更新,我的解决方法(目前)是在需要新位置时手动调用requestLocationUpdates,然后只使用第一个可用位置。为了在较短的时间间隔执行此操作,我使用handler.postDelayed(myRunnable, updateInterval)来延迟来电,然后myRunnable负责调用requestLocationUpdates。但是,这种方法只占50%(显然是随机的)时间。

有没有人知道这个问题,有没有办法解决它?或者我是唯一可以选择设置minTime = 0并希望最好的选择?

源代码

以下是myRunnable的源代码,我使用run()定期手动调用handler.postDelayed(myRunnable, updateInterval)方法:

public class MyRunnable implements Runnable {
    private LocationManager manager;
    private LocationListener listener;

    @Override
    public void run() {
        // This is called everytime a new update is requested
        // so that only one request is running at a time.
        removeUpdates();

        manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        listener = new LocationListener() {
            @Override
            public void onLocationChanged(Location loc) {
                location = loc;
                latitude = loc.getLatitude();
                longitude = loc.getLongitude();
                accuracy = Math.round(loc.getAccuracy());

                handler.sendMessage(Message.obtain(handler, KEY_MESSAGE_LOCATION_CHANGED));

                checkForArrival();
            }

            // Other overrides are empty.
        };

        if(!arrived)
            manager.requestLocationUpdates(provider, updateInterval, 0, listener);
    }

    /**
     * Removes location updates from the LocationListener.
     */
    public void removeUpdates() {
        if(!(manager == null || listener == null))
            manager.removeUpdates(listener);
    }

    // Another method for "cleaning up" when the user has arrived.
}


这是我的handler

handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case KEY_MESSAGE_LOCATION_CHANGED:
                if(myRunnable != null) {
                    myRunnable.removeUpdates();
                    handler.postDelayed(myRunnable, updateInterval);
                }
                break;
            }
        }
    };


其他信息

整个位置更新服务在服务中运行。

我已多次阅读该文档,谷歌解决了这个问题,并尝试了其他各种解决方法。什么都没有。

我已经记录了这个该死的东西,唯一令人兴奋的事情是我的频繁位置请求的一个大胖子“忽略”。所有正确的方法都被称为。

任何帮助非常赞赏!

3 个答案:

答案 0 :(得分:18)

你是完全正确的,在Android中对最小时间45秒进行了编码。

这似乎是一个NetworkLocationProvider类源代码,当它仍在Android核心中时:

http://www.netmite.com/android/mydroid/frameworks/base/location/java/com/android/internal/location/NetworkLocationProvider.java

查看变量:

private static final long MIN_TIME_BETWEEN_WIFI_REPORTS = 45 * 1000; // 45 seconds

方法:

@Override
public void setMinTime(long minTime) {
    if (minTime < MIN_TIME_BETWEEN_WIFI_REPORTS) {
        mWifiScanFrequency = MIN_TIME_BETWEEN_WIFI_REPORTS;
    } else {
        mWifiScanFrequency = minTime;
    }
    super.setMinTime(minTime);
}

现在NetworkLocationProvider不在Android核心中,您可以在/ system / app中的NetworkLocation.apk中找到它

你可以在这里找到解释为什么不在核心的解释:

https://groups.google.com/forum/?fromgroups=#!topic/android-platform/10Yr0r2myGA

但是45秒的时间似乎仍然存在。 看看这个NetworkProvider反编译:

http://android.fjfalcon.com/xt720/miui-trans/apk-decompiled/NetworkLocation/smali/com/google/android/location/NetworkLocationProvider.smali

.line 149
const-wide/32 v4, 0xafc8

iput-wide v4, p0, Lcom/google/android/location/NetworkLocationProvider;->mWifiScanFrequency:J

正如您可能猜到的,如果将0xafc8转换为十进制,则会得到45000毫秒

我还没有找到为什么45秒的解释。我想有一些理由可以避免服务超载或者他们不想要的其他用途。

事实上,Geolocation API有100个请求礼貌限制:

https://developers.google.com/maps/documentation/business/geolocation/#usage_limits

但他们似乎并不尊重Google地图应用中的此规则。如果您打开它并且只有活动的网络位置,您可以注意到您的位置更新频率超过45秒。

当谷歌地图开放时,我注意到这条线在logcat中经常出现频繁(每秒33次):

02-20 17:12:08.204:V / LocationManagerService(1733):getAllProviders

我猜Google地图也会再次调用removeUpdates()和requestLocationUpdates()来获取新职位。

所以我认为没有解决办法,如果你想在45秒内获得一个网络位置,这是你能做的最好的。

答案 1 :(得分:7)

您可以将minTime设置为任何值。但是,只有在新位置可用时,您才会获得更新。网络只在我拥有的每部手机上每隔45秒左右更新一次。这似乎是网络提供商的限制。如果您想要更频繁的更新,请使用GPS提供商。根据GPS硬件的不同,您应该获得大约4Hz的最大更新速率。

答案 2 :(得分:0)

我遇到了类似的问题。我在locationManager.requestSingleUpdate()结束时拨打了onLocationChanged(),并强制退回更新。您可以设置延迟命令然后执行requestSingleUpdate,确保注册包含locationListener

我正在尝试创建GPS时钟,但更新不一致,更新时间从1-5秒左右。但它可能适用于其他应用程序。