这是我注册我的应用以接收位置更新的方式:
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(Consts.ONE_MINUTE * 10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setFastestInterval(Consts.ONE_MINUTE);
Builder builder = new GoogleApiClient.Builder(context);
builder.addApi(ActivityRecognition.API);
mGoogleApiClient = builder.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
....
....
@Override
public void onConnected(Bundle connectionHint) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationUpdatespendingInent);
}
我的待处理意图几乎按照确切的请求间隔在后台调用...
到目前为止一切顺利。
问题:当WIFI被禁用/未连接到任何网络,或者没有启用3G / 4G网络数据时 - 融合位置提供商不提供新的位置更新!!
我的位置访问设置已打开,GPS卫星和WI-FI&检查移动网络位置。
更大的问题:有时在这种情况下,我会通过待处理的意图接收位置更新回调,但是它知道的最后一个位置(即使是一小时前,我也是很长很远离那个地方很远的地方)
根据PRIORITY_BALANCED_POWER_ACCURACY
的文档:
与setPriority(int)一起使用以请求“块”级别的准确性。 块级精度被认为是大约100米的精度。使用这种粗略的精度通常会消耗更少的功率。
我期待融合位置提供商在没有其他选择时打开GPS,或者如果他没有其他选择,至少不会提供新的位置更新。
另一个不可预测和令人不安的问题:
我将PRIORITY_BALANCED_POWER_ACCURACY
更改为PRIORITY_HIGH_ACCURACY
以查看其行为(24小时)。所有间隔保持不变(更新之间间隔10分钟)。即使在没有网络/ SIM卡的手机中也确实收到了准确的位置,但是 - 电池耗尽快!当我查看电池历史时,我惊讶地看到 GPS无线电一直处于完全传输模式!!!! 我在日志中也看到每分钟收到一个位置,甚至我每十分钟请求一次位置(我没有任何其他安装的应用程序打开GPS接收位置..)
我注意到在多个设备(例如Moto X 2013,HTC One X,Nexus 5)上的这种行为,所有设备都带有最新的Google Play服务(版本6.1.11)和Android KITKAT 4.4.4
我的应用程序在很大程度上取决于用户当前位置,并且只要用户登录,就会定期在指定的时间间隔内接收位置更新,因此我不想使用PRIORITY_HIGH_ACCURACY
模式,以防止电池漏..
我的问题:
是融合位置提供商,如果设置为使用PRIORITY_BALANCED_POWER_ACCURACY
接收更新并且没有任何WI-FI或手机信息塔信息,则假设完全使用GPS?
如果确实如此,那么我做错了什么?
为什么我得到这种误导性的位置更新不正确? (正如我在“更大问题”一节中所解释的那样......
为什么GPS广播一直打开,而不是在我使用PRIORITY_HIGH_ACCURACY
参数时间隔10分钟打开? (我没有其他安装的应用程序更快地触发位置更新..)
答案 0 :(得分:19)
对于指定的问题,
1。 是融合位置提供商,如果设置为使用PRIORITY_BALANCED_POWER_ACCURACY
接收更新并且没有任何WI-,则假设完全使用GPS FI或手机信息塔信息?的&安培; 强>
2。 如果有,那么我做错了什么?
显然,在文档中的任何位置都没有指定明确的唯一源。使用PRIORITY
选项,即使通过代码,获得的location
的“来源”也是“融合”。
[location.getProvider()
返回:“融合”]
我已经看到只有当LocationRequest具有PRIORITY_HIGH_ACCURACY时才使用GPS。所以它在其他条件下不使用GPS。
4。 为什么GPS广播一直打开,而不是在我使用PRIORITY_HIGH_ACCURACY参数时间隔10分钟打开? (我没有其他安装的应用程序更快地触发位置更新..)
最快间隔设定为1分钟。根据我的理解,当最快间隔的值的持续时间短于setInterval的值时,setFastestInterval优先于setInterval。
在你的情况下,1分钟对10
关于没有其他已安装的应用程序触发位置更新,它仅作为示例给出,并没有明确指定只有那种情况。
这可以控制应用程序收到的最快速率 位置更新,在某些情况下可能比setInterval(long)更快 情况(例如,如果其他应用程序正在触发位置 更新)。
所以,PRIORITY_HIGH_ACCURACY
会发生什么,它在最快的间隔设置上请求location
- 1分钟,使用GPS(专门的类型)。
3。 为什么我收到这些误导性的位置更新不正确? (正如我在“更大问题”一节中所解释的那样......
还需要检查pendingIntent
机制的代码。虽然可能有一些事情要注意:
您可以添加location.getTime()
以确保并验证获取位置的时间。如果范围内没有wifi-cell塔并且使用PRIORITY_BALANCED_POWER_ACCURACY
,则很可能没有更新
第一个位置的块级准确度,在调用“lastKnown”时使用将无济于事。
电池消耗量是因为GPS和1分钟更新的结合。尝试将最快间隔设置为5或10分钟(如果适合您的实施),但如果您需要绝对准确的位置,则PRIORITY_BALANCED_POWER
可能无效。我通常会添加对onLocationChanged
中获取的位置的检查,并根据该位置,在LocationRequest中切换优先级。它肯定有助于获得一个位置,除非我在一个没有GPS视线和Wifi网络的建筑物内。
答案 1 :(得分:4)
我建议您一起使用AlarmManager
和FusedLocationProvider
,以便每隔10分钟发出AlarmManager
个火警,以便开始更新位置。
获得更新位置后,断开位置客户端。您不需要通过在LocationRequest
中设置间隔时间来保持其一直运行,而是可以使用AlarmManager
在每个时间间隔调用该过程。
在这种机制中,您将获得以下好处,以解决您的问题:
我希望它会有所帮助。
答案 2 :(得分:3)
Cell tower覆盖了几英里的区域,因此它们不是最适合获取位置的区域。使用位置时,请查看位置准确性。
@Override
public void onLocationChanged(Location location) {
//it happens
if (location == null) {
return;
}
// all locations should have an accuracy
if (!location.hasAccuracy()) {
return;
}
// if its not accurate enough don't use it
// this value is in meters
if (location.getAccuracy() > 200) {
return;
}
}
您可以将广播接收器置于网络状态,当没有连接时,您可以使用priority_high_accuracy重新启动您的位置提供商,仅当用户启用GPS时才会使用GPS,否则它会回到wifi和手机信号塔上。
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
/** Checks whether the device currently has a network connection */
private boolean isDeviceOnline() {
ConnectivityManager connMgr = (ConnectivityManager) activity
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
答案 3 :(得分:0)
要更新GPS坐标,您还可以使用GPS和WI-FI提供商。用于更新位置使用以及最小距离参数。我将为您提供小型GPS服务示例。
答案:
1)PRIORITY_BALANCED_POWER_ACCURACY not使用GPS。
2)使用GPS和WI-FI检测位置。
3)PRIORITY_BALANCED_POWER_ACCURACY可能是因为区域内没有WI-FI。
代码示例:
public class GPSservice extends Service implements LocationListener {
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 2;
private static final long MIN_TIME_BW_UPDATES = 1000 * 1;
double latitude, longitude;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
boolean canGetLocation = false;
Location location;
protected LocationManager locationManager;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
getLocation();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onLocationChanged(Location location) {
new LocationReceiver(location, getApplicationContext());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
public Location getLocation() {
try {
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// getting GPS status
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
Log.d("Network", "NO network");
} else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
}