FusedLocationProviderClient getLastLocation elapsedRealtimeNanos主要是当前系统时间

时间:2018-02-28 16:39:31

标签: android location google-play-services android-fusedlocation fusedlocationproviderclient

更新2

我在谷歌I / O '18与谷歌工程师谈过话。他告诉我,我可以信任fusedLocationProvider。如果他用新的时间戳标记最后一个已知位置,则用户可能仍在同一位置。

我希望将来使用“移动”设备进行一些测试,以证明这一说法。

原始问题

我正在使用FusedLocationProviderClientgetLastLocation()请求最后一个已知位置,并想要检查上一个已知位置是否超过5分钟,以便开始新的位置请求。

在我的测试过程中,我发现了一个奇怪的行为,其位置elapsedRealtimeNanos应该用于compare

出于测试目的,我在简单的Java线程中每秒请求最后一个已知位置。收到位置后,我会检查elapsedRealtimeNanos并将它们与SystemClock.elapsedRealtimeNanos()进行比较。在大多数情况下,最后一个已知位置的年龄也设置为SystemClock.elapsedRealtimeNanos(),因此差异接近0.这意味着FusedLocationProvider告诉我最后一个已知位置的修复现在是正确的,这使得年龄检查不可靠。

这种行为很奇怪,但情况越来越糟。

当我在测试会话期间启动并行位置请求或启动Google地图时,最后一个已知位置的elapsedRealtimeNanos会停止增长,并且只会在找到“真正的”新位置时更新到更新的位置。这应该是我期望的默认行为。

我在不同的位置设置中观察到此行为,例如HIGH_ACCURACY和SENSORS_ONLY。

这是否意味着,检查最后一个已知位置的年龄是不可能的?任何人都可以解释这种行为吗?

更新1

location.getTime()

的行为相同

代码段:

 @Override void getLastKnownLocation() {
    try {
        mLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
            @Override
            public void onComplete(@NonNull Task<Location> task) {
                try {
                    Location location = task.getResult();
                    if (location != null) {
                        location.getElapsedRealtimeNanos()
                        //Compare to SystemClock.elapsedRealtimeNanos();
            ...

和(我知道它凌乱)

      new Thread(){
        @Override public void run() {
            locationFinder.getLastKnownLocation();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            run();
        }
    }.start();

位置更新请求

public PlayServicesLocationFinder(Context context){
    mLocationClient = LocationServices.getFusedLocationProviderClient(context);
}

@Override
public void getLocationUpdates() {

    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setInterval(60000); 
    locationRequest.setFastestInterval(15000);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    mLocationClient.requestLocationUpdates(locationRequest, continuousUpdatesLocationListener, null);
}

2 个答案:

答案 0 :(得分:1)

也许我可以建议您尝试其他方式来获得“新鲜”坐标,这似乎是您的代码的主要目标。 也许你可以试试:

  • 首先获取 LastKnownLocation
  • 获得LastKnownLocation后。你可以开始 requestLocationUpdates(),一旦你有一个与lastKnownLocation不同的新坐标,那么那个是你的“新鲜”坐标。您甚至可以实现精确度控制,以获得“准确和更新”的坐标。

我使用了之前的方案,它可以完美地获得当前位置,而无需验证位置GPS时间(getTime())。

注意:我知道这不是电池友好的,但您可以控制LocationRequest中的更新次数,间隔时间,最长等待时间,以便将电池消耗保持在最小。

答案 1 :(得分:0)

有办法解决此要求。 您将使用updatedLocation计算savedLocation,是否存储新位置。 两个属性可以帮助您进行此计算。

  • 两个地点之间的距离。
  • 获取的位置的时间。 (你的要求)

首先,您必须使用

存储位置返回
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                    mGoogleApiClient);

然后将其与下一个获取的位置进行比较(两个属性都会为您提供更好的跟踪来管理设备位置更新), 然后决定新取出的位置是否应该替换为存储位置。 为此你已经写了你的逻辑,以为我可以分享一些可以帮助你的代码。

private boolean isTimeToUpdateLocation(Location newlocation) {
    int LOCATION_ALERT_FREQUENCY = 60000; //1 * 60000; // 1 minute
    long timeDelta = System.currentTimeMillis() - newlocation.getTime();
    return (timeDelta >= LOCATION_ALERT_FREQUENCY);
}

关于距离的位置更新,有一小段代码

int LOCATION_DEVIATION = 1000; // 1 KM

public boolean shouldUpdateNewLocation(Location location) {

    Location prevLocation = getLastStoredLocation();

    boolean shouldUpdateToServer = false;

    if (prevLocation != null) {
        if (prevLocation.distanceTo(location) > LOCATION_DEVIATION)
            shouldUpdateToServer = true;
    }

    return shouldUpdateToServer;
}

我希望您现在可以解决您所面临的问题。