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

ste*_*sen 23 android location

背景

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

问题

当我测试它(provider = LocationManager.NETWORK_PROVIDER),以调用requestLocationUpdates(provider, minTime, minDistance, locationListener)任何minTime < 45000具有相同的效果minTime = 45000,也就是我获得更新与间隔正好 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.
}
Run Code Online (Sandbox Code Playgroud)


这是我的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;
            }
        }
    };
Run Code Online (Sandbox Code Playgroud)


附加信息

整个位置更新事物在服务中运行.

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

我已经把这个该死的东西记录下来了,唯一令人兴奋的事情是我的频繁位置请求"忽略"了.调用所有正确的方法.

任何帮助将非常感谢!

djp*_*ado 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
Run Code Online (Sandbox Code Playgroud)

方法:

@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);
}
Run Code Online (Sandbox Code Playgroud)

现在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
Run Code Online (Sandbox Code Playgroud)

正如您可能猜到的,如果将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 Maps也会再次调用removeUpdates()和requestLocationUpdates()来获取新位置.

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


Fro*_*zie 8

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