Android - 可靠地获取当前位置

8

我的应用程序会在特定时间检查用户是否在指定位置。我使用闹钟管理器启动服务来进行此调用:

locationManager.requestLocationUpdates(bestProvider, 0, 0, listener);

同时还需要进行以下检查:

 locationManager.getLastKnownLocation(bestProvider);

但是当我在真实设备上运行时,会遇到一些问题。首先,getLastKnownLocation 很可能是GPS最后一次存在的地方,这可能是任何地方(即可能与用户当前位置相距几英里)。所以,我只需要等待 requestLocationUpdates 回调,如果在两分钟内没有回调,则移除监听器并放弃,对吗?

错了,因为如果用户的位置已经稳定(即他们最近使用了GPS并且没有移动),那么我的监听器将永远不会被调用,因为位置不会发生变化。但GPS会一直运行,直到移除了监听器,耗尽电池...

获取当前位置的正确方法是什么,而不是将旧位置误认为当前位置?我不介意等待几分钟。

编辑:我可能错误地认为监听器不会被调用,可能需要更长的时间...很难说。我仍然希望得到一个明确的答案。

2个回答

4
代码可能类似这样:
public class MyLocation {
    Timer timer1;
    LocationManager lm;

    public boolean getLocation(Context context)
    {
        lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
        timer1=new Timer();
        timer1.schedule(new GetLastLocation(), 20000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            lm.removeUpdates(this);
            //use location as it is the latest value
        }
        public void onProviderDisabled(String provider) {}
        public void onProviderEnabled(String provider) {}
        public void onStatusChanged(String provider, int status, Bundle extras) {}
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
             lm.removeUpdates(locationListenerGps);
             Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
             //use location as we have not received the new value from listener
        }
    }
}

我们开始监听并等待一段时间(在我的例子中是20秒)。如果在此期间内收到更新,我们将使用它。如果在此期间内没有收到更新,则使用getLastKnownLocation值并停止监听器。
您可以在这里查看完整的代码What is the simplest and most robust way to get the user's current location on Android? 编辑(由提问者):这是大部分答案,但我的最终解决方案使用Handler而不是计时器。

你能提供一些示例代码吗?例如,如果位置监听器没有被调用,你将如何等待2分钟或类似的操作? - noah

4
如果用户的位置已经稳定,那么getLastKnownLocation将返回当前位置。我会先调用getLastKnownLocation,查看时间戳(比较Location.getElapsedRealTimeNanos()SystemClock.elapsedRealTimeNanos()),然后如果修复过时,注册一个监听器。

谢谢,我不知道getTime()。问题在于,时间要多久才被位置提供者认为太旧?如果我不使用那个位置,如何保证我的监听器会被调用? - noah
1
位置提供者不会考虑它是否太旧,它从不丢弃它(据我所知)。您必须决定何时认为修复已经过时并在必要时请求更新。如果在一定时间内没有更新,则仍然可以使用旧位置。 - cristis
2
这里有一个小问题:API没有定义Location.getTime()返回的时间戳的来源。对于GPS,它似乎是卫星时间。对于网络提供商,它似乎是本地设备时间。这使得可靠地确定位置的年龄有些困难 - 考虑到用户的时钟可能不准确或时区可能配置错误的可能性。 - sstn
1
你可以使用 location.getElapsedRealTimeNanos() 替代 location.getTime(),然后与 SystemClock.elapsedRealTimeNanos 进行比较,以获取更准确的位置修复时间。 - Sid
是的,但请记住location.getElapsedRealTimeNanos()仅在API级别17中添加。 - cassi.lup

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