GPS定位启动时间过长
GPS locating takes too long to start
我在我的应用程序中设置了一个 LocationManager 来定位用户并显示他的当前位置。
这工作正常,除了启动时间太长(有时 >10 秒)。在开始时间后,服务按预期工作。
这是日志输出。第一行是启动时的 LastKnownLocation
,LocationService 将在 18 秒后启动...
05-04 09:14:29.301 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986175,x,121746 acc=14 et=+2d11h37m45s435ms alt=165.0 vel=0.0 {Bundle[mParcelledData.dataSize=40]}]
[...]
05-04 09:14:47.943 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986343,x,121702 acc=33 et=+2d11h40m57s443ms alt=149.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
05-04 09:14:48.940 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986351,x,121693 acc=30 et=+2d11h40m58s442ms alt=134.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
05-04 09:14:49.948 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986373,x,121666 acc=28 et=+2d11h40m59s448ms alt=160.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
[...]
这是我当前的代码:
创建时:
SupportMapFragment mapFragment
= (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
onMyMapReady(googleMap);
}
});
onMyMapReady:
private void onMyMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
askPermissionsAndShowMyLocation();
}
});
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setAllGesturesEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
askPermissionsAndShowMyLocation()
是请求 ACCESS_COARSE_LOCATION
和 ACCESS_FINE_LOCATION
许可的简单方法。成功时(或低于 API 23)将调用方法 showMyLocation()
。
showMyLocation(正如我在日志中看到的,这将在启动时没有任何巨大延迟地被调用):
private void showMyLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
String locationProvider = this.getEnabledLocationProvider();
if (locationProvider == null) {
dialogCheckGps();
return;
}
Log.d(LOG_TAG, "Location provider: " + locationProvider);
try {
mLocationManager.requestLocationUpdates(
locationProvider,
0,
0, this);
currentLocation = mLocationManager
.getLastKnownLocation(locationProvider);
} catch (SecurityException e) {
Log.e(LOG_TAG, "Show My Location Error:" + e.getMessage());
}
///////////////////
// This is the first log entry from above.
///////////////////
if (currentLocation != null) {
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL));
moveToLocation(currentLocation);
} else {
Log.d(LOG_TAG, "Location not found");
}
}
onLocationChanged(应立即调用,但会延迟调用,如您在上面的日志中所见):
@Override
public void onLocationChanged(Location location) {
moveToLocation(location);
}
谁有好的解决方案可以更快地更新位置?
提前致谢。
获取 GPS 锁定所需的时间取决于信号强度。但是,您可以执行一些操作以使其看起来 "faster"。
您有三种不同的提供商类型:
PASSIVE_PROVIDER
非常快的锁定
没有额外的电源要求
精度低(除非在有很多无线接入点的区域)- ~ 1 英里
NETWORK_PROVIDER
使用 GPS + 手机网络获得快速初始定位
非常低功耗
相当准确 - ~100 - 200 英尺
GPS_PROVIDER
使用 GPS 并且需要很长时间才能定位
非常准确 - ~10 - 20 英尺
现在您可以从检查最低准确度到最高准确度开始,同时在地图上确定他们的位置。但是,您必须检查设备以查看网络或提供商访问是否可用。您可以使用
LocationManager.getProviders(boolean enabledOnly)
LocationManager.isProviderEnabled(String provider)
在 UI 中表示这一点的一种方法可能是进一步缩小缩放级别,然后在您尝试获得更好的修复时重新居中并放大以实现平滑过渡。
我注意到的另一件事是,您在创建地图后请求您的许可。由于它是异步加载,您可以在加载地图时启动 LocationManager GPS 精确定位。您可以在代码的 onCreate 部分执行此操作。
我在我的应用程序中设置了一个 LocationManager 来定位用户并显示他的当前位置。 这工作正常,除了启动时间太长(有时 >10 秒)。在开始时间后,服务按预期工作。
这是日志输出。第一行是启动时的 LastKnownLocation
,LocationService 将在 18 秒后启动...
05-04 09:14:29.301 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986175,x,121746 acc=14 et=+2d11h37m45s435ms alt=165.0 vel=0.0 {Bundle[mParcelledData.dataSize=40]}]
[...]
05-04 09:14:47.943 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986343,x,121702 acc=33 et=+2d11h40m57s443ms alt=149.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
05-04 09:14:48.940 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986351,x,121693 acc=30 et=+2d11h40m58s442ms alt=134.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
05-04 09:14:49.948 23688-23688/xxxxx D/MainActivity: Moving GMaps to location Location[gps x,986373,x,121666 acc=28 et=+2d11h40m59s448ms alt=160.0 vel=0.25 bear=139.8 {Bundle[mParcelledData.dataSize=40]}]
[...]
这是我当前的代码:
创建时:
SupportMapFragment mapFragment
= (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
onMyMapReady(googleMap);
}
});
onMyMapReady:
private void onMyMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
askPermissionsAndShowMyLocation();
}
});
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mMap.getUiSettings().setAllGesturesEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
askPermissionsAndShowMyLocation()
是请求 ACCESS_COARSE_LOCATION
和 ACCESS_FINE_LOCATION
许可的简单方法。成功时(或低于 API 23)将调用方法 showMyLocation()
。
showMyLocation(正如我在日志中看到的,这将在启动时没有任何巨大延迟地被调用):
private void showMyLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mMap.setMyLocationEnabled(true);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
String locationProvider = this.getEnabledLocationProvider();
if (locationProvider == null) {
dialogCheckGps();
return;
}
Log.d(LOG_TAG, "Location provider: " + locationProvider);
try {
mLocationManager.requestLocationUpdates(
locationProvider,
0,
0, this);
currentLocation = mLocationManager
.getLastKnownLocation(locationProvider);
} catch (SecurityException e) {
Log.e(LOG_TAG, "Show My Location Error:" + e.getMessage());
}
///////////////////
// This is the first log entry from above.
///////////////////
if (currentLocation != null) {
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL));
moveToLocation(currentLocation);
} else {
Log.d(LOG_TAG, "Location not found");
}
}
onLocationChanged(应立即调用,但会延迟调用,如您在上面的日志中所见):
@Override
public void onLocationChanged(Location location) {
moveToLocation(location);
}
谁有好的解决方案可以更快地更新位置?
提前致谢。
获取 GPS 锁定所需的时间取决于信号强度。但是,您可以执行一些操作以使其看起来 "faster"。
您有三种不同的提供商类型:
PASSIVE_PROVIDER
非常快的锁定
没有额外的电源要求
精度低(除非在有很多无线接入点的区域)- ~ 1 英里
NETWORK_PROVIDER
使用 GPS + 手机网络获得快速初始定位
非常低功耗
相当准确 - ~100 - 200 英尺
GPS_PROVIDER
使用 GPS 并且需要很长时间才能定位
非常准确 - ~10 - 20 英尺
现在您可以从检查最低准确度到最高准确度开始,同时在地图上确定他们的位置。但是,您必须检查设备以查看网络或提供商访问是否可用。您可以使用
LocationManager.getProviders(boolean enabledOnly)
LocationManager.isProviderEnabled(String provider)
在 UI 中表示这一点的一种方法可能是进一步缩小缩放级别,然后在您尝试获得更好的修复时重新居中并放大以实现平滑过渡。
我注意到的另一件事是,您在创建地图后请求您的许可。由于它是异步加载,您可以在加载地图时启动 LocationManager GPS 精确定位。您可以在代码的 onCreate 部分执行此操作。