地理位置手表不会持续触发

Posted

技术标签:

【中文标题】地理位置手表不会持续触发【英文标题】:Geolocation watch doesn't fire consistently 【发布时间】:2015-08-01 17:19:38 【问题描述】:

我有一个测试应用程序,它从 html5 地理定位服务获取 lat/lng 值。不幸的是,它以相当不一致的时间间隔发射,从 500 毫秒到 10000 毫秒不等。我已经尝试更改手表的 maximimAge 和 timeout 参数,但这些似乎并没有改变任何东西。我正在 Chrome 中以及通过 android Lollipop 构建上的简单 Cordova 应用程序对其进行测试。下面的代码仅显示手表的时间戳值,以消除可能导致问题的任何其他延迟。似乎该间隔接近 1 秒然后 5 秒的重复模式。我还尝试将地理位置获取函数放在 setInterval 函数中,它的行为具有相同的 1 秒和 5 秒重复间隔。

<html>
<body>
    <h1>Timestamp</h1>
    <div id="mytimestamp"></div>
    <button id="btnstopwatch">Stop GPS</button>
</body>
</html>

<script type="text/javascript">
    var mytimestamp = document.getElementById("mytimestamp");
    //start watching location
    watchPositionId = navigator.geolocation.watchPosition(updateCompass,handleerror,
        enableHighAccuracy:true, 
        maximumAge:3000, 
        timeout:3000
    );

function updateCompass(p)

    mytimestamp.innerHTML = p.timestamp;


function handleerror(err)

    if(err.code ==1)
    
        //user said no
        alert('Please allow access to GPS');
    
    else
    
        alert(err.code);
    

</script>

【问题讨论】:

【参考方案1】:

关于 watchPosition(),在下面的 link w3 中说“只有在获得新位置时才调用successCallback ......实现可能会对频率施加限制回调,以避免无意中消耗不成比例的资源。”

这意味着 watchPosition() 正在等待会导致位置发生变化的事件,否则它什么也不做。所以 watchPosition() 不会调用 updateCompass() 除非它看到位置的变化。 另外,关于watchPosition(),maximumAgetimeout参数与获取新位置有关,这些参数与watchPosition()的次数和时间无关被称为...

WatchPosition() 防止连续调用以查看位置是否发生变化,并且仅在发生与位置变化相关的某些事件时才做出反应,这有助于节省电池等资源。但是如果你真的想看位置,比如说每三秒一次,不管位置是否改变,我认为设置一个间隔是个好方法。

var watchPositionId;
   //start watching location
    setInterval(function () 
    watchPositionId = navigator.geolocation.watchPosition(updateCompass, handleerror, 
        enableHighAccuracy: true,
        maximumAge: 3000,
        timeout: 3000
    );
    , 3000);

    function updateCompass(p) 
        mytimestamp.innerHTML = p.timestamp;
        // if you have alert message it will counts seconds once you dismiss the alert,
        //this may be part of the issue why you kept getting diffrent intervals.
        //alert(p.timestamp);
        navigator.geolocation.clearWatch(watchPositionId);
    

您提到您尝试 setInterval 但它不起作用,所以请注意我在上面的代码中注释了 alert() 因为它导致我有延迟,没有它,html 中的时间戳每 3000 毫秒更新一次精度约5ms。

如果您想使用 watchPosition(),上述方法有效,因为 clearWatch() 会停止 watchPosition() 并进一步回调。基本上,上面的代码每三秒启动一次新的 watchPosition() 并用 clearWatch() 终止它。话虽如此,我认为 watchPosition() 不是在这种方法中使用的最佳方法,除非您预计在此时间间隔内位置会发生重大变化。我宁愿使用 getCurrentPosition() ,因为它可以完成工作并且不等待位置变化。

 var watchPositionId;
   //start watching location
    setInterval(function () 
        watchPositionId = navigator.geolocation.getCurrentPosition(updateCompass, handleerror, 
        enableHighAccuracy: true,
        maximumAge: 3000,
        timeout: 3000
    );
    , 3000);

    function updateCompass(p) 
        mytimestamp.innerHTML = p.timestamp;
    

【讨论】:

我将代码更改为使用 getCurrentPosition 函数,现在它会在 4.5 到 6.5 秒之间更新。我很快将把它加入到 Cordova 应用程序中,看看它是否会继续以这种方式运行。目前,我可以忍受这种不一致,希望它在编译成本机代码后会变得更加一致。 请记住,如果您的代码中有 alert(),则在您单击警报上的“确定”按钮后,时间间隔的时间就会开始计算,因此您的时间戳将具有比预期更长的时间。 【参考方案2】:

我最终将解决方案更改为同时使用地理位置和 deviceOrientationEvent。单独使用地理定位事件会产生非常“生涩”的响应,而设备方向事件可以消除这种情况。

这里的 setInterval 函数设置为每十秒获取一次地理位置:

window.onload = function()

    //fetch new GPS info every 10000 milliseconds
    window.setInterval(function ()
    
        navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoFailure, 
        enableHighAccuracy: true,
        maximumAge: 0,
        timeout: 30000 //large timeout to accomodate slow GPS lock on some devices
    );
    , 10000);  //update current location every ten seconds
;

关于地理上的成功:

function onGeoSuccess(location)


    //call function to calculate bearing
    var cluebearing = geo.bearing(currentlat, currentlng, cluelat, cluelng);

    //call function to rotate arrow
    rotateArrow(cluebearing);
//end onGeoSuccess()

获取设备方向和进程的功能:

function rotateArrow(mybearing)

    //Check for support for DeviceOrientation event
    if(window.DeviceOrientationEvent)
     
        //orientation listener
        window.addEventListener('deviceorientation', function(event)
        
            var myalpha = event.alpha; //rotation from north
            //process orientation change
        //end deviceorientation listener
    
//end rotateArrow()

关于地理故障:

function onGeoFailure()

    alert('Please turn on your phone\'s GPS');

【讨论】:

以上是关于地理位置手表不会持续触发的主要内容,如果未能解决你的问题,请参考以下文章

Angular 手表不会在值更改时触发

Android地理围栏不会触发一次位置关闭和再次打开[重复]

没有 requestLocationUpdates 不会触发 Android 地理围栏

苹果手表中的多个位置

在后台应用程序时不会触发地理围栏通知

应用程序在后台时不会触发地理围栏转换