Android 的 FusedLocationApi 不激活 GPS 并返回非常旧的日期
Posted
技术标签:
【中文标题】Android 的 FusedLocationApi 不激活 GPS 并返回非常旧的日期【英文标题】:Android's FusedLocationApi doesn't activate GPS and returns very old dates 【发布时间】:2017-10-23 02:58:50 【问题描述】:我在一个应用中编写了一些逻辑,用于每 15 分钟采样一次用户的位置。我只对获取用户位置的样本感兴趣,而不是持续跟踪他。
在真实设备上进行测试(启用位置设置)后,我发现我只能在连接到 WiFi 时管理获取位置。但是当我没有连接时(比如走在街上),FusedLocationApi.getLastLocation 函数会返回连接到 WiFi 时采样的旧位置,并且永远不会激活 GPS 来尝试获取真实的当前位置。
虽然我知道我可以过滤掉旧位置,但我不确定如何让 FusedLocationApi 激活 GPS(或至少返回最新位置)。 另一个限制是我不想让 GPS 开启太久,也不想耗尽用户的电量。
在下面的代码中,我连接到 GoogleApiClient 并尝试获取最后一个已知位置。如果此值为空,我会注册以从中获取位置更新,并且一旦获得位置更新(或经过允许的等待时间),我就会断开连接。
我已经对此进行了一整天的测试,FusedLocationApi 不断返回它早上在 WiFi 中采样的旧位置。
/**
* First function in the location collection chain.
* This function is called from outside whenever a client wants to get the user's current location.
*/
public void GetCurrentLocation(Context context, final LocationCallbackable callback)
currentContext = context;
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null)
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Add the given callback to the callback list. This will be used to return the location to whoever requested it.
callbacks.add(callback);
// Connect to GoogleApiClient. When connected, this will trigger onConnected and then we'll be able to request the user's location.
mGoogleApiClient.connect();
@Override
public void onConnected(@Nullable Bundle bundle)
// Create a location request.
LocationRequest locationRequest = createLocationRequest();
// Check if we don't have permissions to get fine location.
if (ActivityCompat.checkSelfPermission(currentContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
// If we no permissions were granted - call the given callback with null.
runCallback(null);
return;
// If we got here, we have permissions :)
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location != null)
// Disconnect from GoogleApiClient.
disconnect();
// Call the callback that the caller has supplied us with, with the location we have.
runCallback(location);
// Location was null - that means the GoogleApiClient didn't have enough time to get the current location.
else
// In that case we should check if location settings are valid, and if so register to locationUpdated.
// If the settings are not valid, we will terminate.
VerifyLocationSettingsAndContinue(locationRequest);
/**
* Verify if the device's settings are valid for location sampling.
* If they are - register to get location updates and unregister once we got it.
* If they are not - the sampling chain is terminated, returning null to the client.
*/
private void VerifyLocationSettingsAndContinue(final LocationRequest locationRequest)
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
final LocationManager _this = this;
// Make sure the user's settings are satisfied.
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
// Set a callback for the pending result.
result.setResultCallback(new ResultCallback<LocationSettingsResult>()
@Override
public void onResult(LocationSettingsResult result)
final Status status = result.getStatus();
switch (status.getStatusCode())
case LocationSettingsStatusCodes.SUCCESS:
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, _this);
// We can get stuck waiting for an update from FusedLocationApi.requestLocationUpdates.
// To solve this, we wait 10 seconds and terminate our self (if we haven't already finished).
new android.os.Handler().postDelayed(
new Runnable()
public void run()
// Only try to stop the operation if we didn't get a location update.
if (!isLocationUpdated)
stopLocationUpdatesAndDisconnect();
runCallback(null);
,
10000);
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
default:
// Location settings are not satisfied. Terminate the location sampling by calling the callback with null.
disconnect();
runCallback(null);
break;
);
@Override
public void onLocationChanged(Location location)
isLocationUpdated = true;
// We got our location sample - unregister ourselves from requesting location updates and disconnect.
stopLocationUpdatesAndDisconnect();
// Call the callback with the location we just got.
runCallback(location);
private void stopLocationUpdatesAndDisconnect()
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
disconnect();
private LocationRequest createLocationRequest()
final LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(4000);
locationRequest.setFastestInterval(1000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set that we only want one update.
locationRequest.setNumUpdates(1);
// If we don't get an update, kill the request after 30 seconds.
locationRequest.setExpirationDuration(30000);
return locationRequest;
【问题讨论】:
您能否指出您正在学习使用 FusedLocationApi 的资源? 来自Google's Android training,用于获取位置并在线阅读大量内容:) 【参考方案1】:当您致电getLastKnownLocation
时,您将获得上次获取点时的最后一个已知位置,但不会获取新点。
例如,如果在您的设备上记录的唯一点是在纽约,并且您前往洛杉矶需要 3 天,然后再记录一个新点(通过您的 VerifyLocationSettingsAndContinue
函数),并且您的应用是唯一一个已请求任何积分,那么当您拨打getLastKnownLocation
时,无论您拨打多少次,您都会从纽约获得 3 天前的积分。
为了获得新积分,您必须请求更新位置。
【讨论】:
感谢您的回复。我在调用时没有请求位置更新: LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, _this) ?我还为此添加了一个侦听器函数(onLocationChanged)(它正在被调用但使用旧位置) 感谢您帮助我意识到,如果我没有从getLastKnownLocation
获得位置,我只会打电话给 requestLocationUpdates
。为了解决我的问题,我现在还使用Location.getElapsedRealtimeNanos()
检查位置是否是最新的,如果不是,我会调用requestLocationUpdates
。
很抱歉在我的帖子中没有提到这一点。很高兴一切顺利!以上是关于Android 的 FusedLocationApi 不激活 GPS 并返回非常旧的日期的主要内容,如果未能解决你的问题,请参考以下文章