从 Android 服务中获得良好的 "path"
Getting a good "path" from an Android service
我正在制作一个可以在地图上绘制用户路径的应用程序。这一切都很好。但是,我也想在应用程序处于后台时继续收集路径(当用户请求时)。这也很好用,但偶尔我会得到 "glitches"。示例见这张地图:
我相信发生的事情是,当我启动服务时,我得到的是 "last known location" 而不是当前位置。到目前为止,我已经尝试了几种技术,但运气不佳。我有过的其他一些想法:
- 正在将 GoogleApiClient 从 Activity 传递到已连接的服务(这可能吗?)
- 忽略服务中的第一个 "X" 位置更新("X" 需要多大?)
- 清理路径,移除"bad"位置(我需要什么样的算法才能弄清楚"bad"位置是什么......在附图中很容易看到,但我不确定如何在代码中做到这一点。
关于处理这种情况的最佳方法还有其他建议吗?
这里有一些代码可以让您了解当前的功能:
Activity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setUpMapIfNeeded();
buildGoogleApiClient();
createLocationRequest();
...
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
Log.v("Connected", String.format("Location: %f, %f, %f", location.getLatitude(), location.getLongitude(), location.getAccuracy()));
if (location != null) {
updateMap();
}
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(pathReceiver);
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
if (isNavigatingTo()) {
Preferences.save(Preferences.PREFERENCE_NAVIGATE_TO, navigateToWaypoint.getId());
} else {
Preferences.remove(Preferences.PREFERENCE_NAVIGATE_TO);
}
if(isRecordingTrack()){
// Start the PathSevice to continue recording the track.
Intent pathServiceIntent = new Intent(this, PathService.class);
pathServiceIntent.putExtra(Utils.PATH_EXTRA, path);
startService(pathServiceIntent);
}
}
...
PathService.java:
@Override
public void onCreate() {
buildGoogleApiClient();
createLocationRequest();
googleApiClient.connect();
super.onCreate();
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onLocationChanged(Location location) {
path.addPoint(location.getLatitude(), location.getLongitude());
}
所以解决方案就在我的问题中......似乎我在从服务返回 activity 时添加了 "last known location"(请参阅 Activity 中的 onConnected class 以上)。
我现在只在 onConnected 中启动位置请求。
我正在制作一个可以在地图上绘制用户路径的应用程序。这一切都很好。但是,我也想在应用程序处于后台时继续收集路径(当用户请求时)。这也很好用,但偶尔我会得到 "glitches"。示例见这张地图:
我相信发生的事情是,当我启动服务时,我得到的是 "last known location" 而不是当前位置。到目前为止,我已经尝试了几种技术,但运气不佳。我有过的其他一些想法:
- 正在将 GoogleApiClient 从 Activity 传递到已连接的服务(这可能吗?)
- 忽略服务中的第一个 "X" 位置更新("X" 需要多大?)
- 清理路径,移除"bad"位置(我需要什么样的算法才能弄清楚"bad"位置是什么......在附图中很容易看到,但我不确定如何在代码中做到这一点。
关于处理这种情况的最佳方法还有其他建议吗?
这里有一些代码可以让您了解当前的功能:
Activity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
setUpMapIfNeeded();
buildGoogleApiClient();
createLocationRequest();
...
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
Log.v("Connected", String.format("Location: %f, %f, %f", location.getLatitude(), location.getLongitude(), location.getAccuracy()));
if (location != null) {
updateMap();
}
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(pathReceiver);
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
if (isNavigatingTo()) {
Preferences.save(Preferences.PREFERENCE_NAVIGATE_TO, navigateToWaypoint.getId());
} else {
Preferences.remove(Preferences.PREFERENCE_NAVIGATE_TO);
}
if(isRecordingTrack()){
// Start the PathSevice to continue recording the track.
Intent pathServiceIntent = new Intent(this, PathService.class);
pathServiceIntent.putExtra(Utils.PATH_EXTRA, path);
startService(pathServiceIntent);
}
}
...
PathService.java:
@Override
public void onCreate() {
buildGoogleApiClient();
createLocationRequest();
googleApiClient.connect();
super.onCreate();
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
@Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onLocationChanged(Location location) {
path.addPoint(location.getLatitude(), location.getLongitude());
}
所以解决方案就在我的问题中......似乎我在从服务返回 activity 时添加了 "last known location"(请参阅 Activity 中的 onConnected class 以上)。
我现在只在 onConnected 中启动位置请求。