ACCESS_COARSE_LOCATION 允许在 Android 上提供基站精度
ACCESS_COARSE_LOCATION permission gives a cell tower precision on Android
我正在使用 FusedLocationApi
中的 requestLocationUpdates()
函数进行一些测试。我正在使用 PRIORITY_BALANCED_POWER_ACCURACY。城市街区精度对我来说很好。
当我请求 ACCESS_FINE_LOCATION 许可时,我得到了大约 100 米的精度,这在关闭 GPS
的情况下非常好。由于我不需要 GPS 精度而是城市街区精度,因此我只想请求 ACCESS_COARSE_LOCATION
权限。但是,当我请求 ACCESS_COARSE_LOCATION
许可时,我得到了 2 公里的精度。该设备似乎不再使用 Wifi
权限,只使用手机信号塔精度。
如何使用 ACCESS_COARSE_LOCATION 权限获得更好的精度?
注意:GPS
在我的测试设备上被禁用。
当您请求 ACCESS_COARSE_LOCATION 权限时,融合位置客户端将为您提供城市街区的准确性,这是预期的行为,并且已写入文档中。看看here下的"Specify App Permissions"
我可以建议您使用常规 android 位置提供程序(不是融合位置)并尝试访问 NETWORK 提供程序。它应该为您提供 WIFI 准确性。
这是一个有趣的问题,我的印象是使用 ACCESS_COARSE_LOCATION
会使用 WiFi,因为文档就是这么说的。
ACCESS_COARSE_LOCATION
的文档指出:
Allows an app to access approximate location derived from network
location sources such as cell towers and Wi-Fi.
所以,我进行了测试,结果令人惊讶。
这是我用来测试的代码:
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
@Override
protected void onPause(){
super.onPause();
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
protected synchronized void buildGoogleApiClient() {
Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
public void onConnected(Bundle bundle) {
Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10);
mLocationRequest.setFastestInterval(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setSmallestDisplacement(0.1F);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
}
@Override
public void onLocationChanged(Location location) {
Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());
Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
build.gradle:
compile 'com.google.android.gms:play-services:7.3.0'
我做的第一个测试是 PRIORITY_BALANCED_POWER_ACCURACY
,没有 WiFi。请注意,我还禁用了 Always Allow Scanning
,因为它指出:
Let Google Location Service and other applications scan for Wi-Fi
networks, even when Wi-Fi is off
因此,如果启用它肯定会扭曲结果。
请注意,我还在所有测试中将定位模式设置为省电模式,因此 GPS 无线电一直处于关闭状态。
以下是 PRIORITY_BALANCED_POWER_ACCURACY
、ACCESS_COARSE_LOCATION
和无 WiFi 的结果:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
所以,它说 2000 米精度,这是实际坐标的距离,绿色箭头显示我实际所在的位置:
然后,我打开WiFi,运行再次测试,结果竟然一模一样!
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
然后,我在 LocationRequest
中切换到 LocationRequest.PRIORITY_LOW_POWER
,同时在 AndroidManifest.xml 中保持 android.permission.ACCESS_COARSE_LOCATION
。
无 WiFi:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
有 WiFi:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
结果还是一样!
使用 PRIORITY_LOW_POWER
与使用 PRIORITY_BALANCED_POWER_ACCURACY
的结果相同,因为 WiFi 状态似乎对坐标精度没有任何影响。
然后,为了涵盖所有基础,我改回 LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
,并将 AndroidManifest.xml 切换为 ACCESS_FINE_LOCATION
:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
第一次测试,没有 WiFi:
accuracy: 826.0 lat: 37.7825458 lon: -122.3948752
所以,它说准确度为 826 米,这是它在地图上的接近程度:
然后,我打开WiFi,结果如下:
accuracy: 18.847 lat: 37.779679 lon: -122.3930918
正如您在地图上看到的那样,它就在字面上:
似乎您在 Java 代码中的 LocationRequest
中使用什么并不重要,而您在 AndroidManifest.xml 中使用什么权限更重要,因为这里的结果清楚地显示使用 ACCESS_FINE_LOCATION
时,打开或关闭 WiFi 无线电会在准确性上产生巨大差异,而且总体上也更准确。
文档似乎有点误导,而且在使用 android.permission.ACCESS_COARSE_LOCATION
时,当您的应用程序是唯一一个使位置请求。
文档指出的另一件事是,使用 PRIORITY_BALANCED_POWER_ACCURACY
将使您的应用程序 "piggy-back" 进入其他应用程序发出的位置请求。
来自文档:
They will only be assigned power blame for the interval set by
setInterval(long), but can still receive locations triggered by other
applications at a rate up to setFastestInterval(long).
因此,如果用户打开 Google 地图,根据文档,您的应用可以获得此时更准确的位置。这是使用新的 Fused Location Provider 而不是旧 API 的主要优势之一,因为它可以减少应用程序的电池消耗量,而无需您做太多工作。
编辑:我对此功能进行了测试,看看使用 ACCESS_COARSE_LOCATION
.
时会发生什么
第一次测试:ACCESS_COARSE_LOCATION
、PRIORITY_BALANCED_POWER_ACCURACY
,WiFi 开启:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662
这让我在水中,离我现在的位置很远。
然后,我退出了测试应用程序,启动了 Google 地图,它准确地定位了我所在的位置,然后重新启动了测试应用程序。
测试应用程序无法从 Google 地图搭载到位置,结果与之前完全相同!
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662
我重新测试了几次,只是为了确定,但看起来使用 ACCESS_COARSE_LOCATION
确实也禁用了应用程序 "piggy-back" 到其他应用程序获得的位置的能力。
看起来在 AndroidManifest.xml 中使用 ACCESS_COARSE_LOCATION
确实削弱了应用程序获取精确位置数据的能力。
总而言之,您唯一真正能做的就是磨练适合您和您的应用程序的最佳设置组合,希望此测试的结果可以帮助您做出决定。
我正在使用 FusedLocationApi
中的 requestLocationUpdates()
函数进行一些测试。我正在使用 PRIORITY_BALANCED_POWER_ACCURACY。城市街区精度对我来说很好。
当我请求 ACCESS_FINE_LOCATION 许可时,我得到了大约 100 米的精度,这在关闭 GPS
的情况下非常好。由于我不需要 GPS 精度而是城市街区精度,因此我只想请求 ACCESS_COARSE_LOCATION
权限。但是,当我请求 ACCESS_COARSE_LOCATION
许可时,我得到了 2 公里的精度。该设备似乎不再使用 Wifi
权限,只使用手机信号塔精度。
如何使用 ACCESS_COARSE_LOCATION 权限获得更好的精度?
注意:GPS
在我的测试设备上被禁用。
当您请求 ACCESS_COARSE_LOCATION 权限时,融合位置客户端将为您提供城市街区的准确性,这是预期的行为,并且已写入文档中。看看here下的"Specify App Permissions"
我可以建议您使用常规 android 位置提供程序(不是融合位置)并尝试访问 NETWORK 提供程序。它应该为您提供 WIFI 准确性。
这是一个有趣的问题,我的印象是使用 ACCESS_COARSE_LOCATION
会使用 WiFi,因为文档就是这么说的。
ACCESS_COARSE_LOCATION
的文档指出:
Allows an app to access approximate location derived from network location sources such as cell towers and Wi-Fi.
所以,我进行了测试,结果令人惊讶。
这是我用来测试的代码:
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
mGoogleApiClient.connect();
}
@Override
protected void onPause(){
super.onPause();
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
protected synchronized void buildGoogleApiClient() {
Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
public void onConnected(Bundle bundle) {
Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10);
mLocationRequest.setFastestInterval(10);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
//mLocationRequest.setSmallestDisplacement(0.1F);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
}
@Override
public void onLocationChanged(Location location) {
Log.d("locationtesting", "accuracy: " + location.getAccuracy() + " lat: " + location.getLatitude() + " lon: " + location.getLongitude());
Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show();
}
}
AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
build.gradle:
compile 'com.google.android.gms:play-services:7.3.0'
我做的第一个测试是 PRIORITY_BALANCED_POWER_ACCURACY
,没有 WiFi。请注意,我还禁用了 Always Allow Scanning
,因为它指出:
Let Google Location Service and other applications scan for Wi-Fi networks, even when Wi-Fi is off
因此,如果启用它肯定会扭曲结果。
请注意,我还在所有测试中将定位模式设置为省电模式,因此 GPS 无线电一直处于关闭状态。
以下是 PRIORITY_BALANCED_POWER_ACCURACY
、ACCESS_COARSE_LOCATION
和无 WiFi 的结果:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
所以,它说 2000 米精度,这是实际坐标的距离,绿色箭头显示我实际所在的位置:
然后,我打开WiFi,运行再次测试,结果竟然一模一样!
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
然后,我在 LocationRequest
中切换到 LocationRequest.PRIORITY_LOW_POWER
,同时在 AndroidManifest.xml 中保持 android.permission.ACCESS_COARSE_LOCATION
。
无 WiFi:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
有 WiFi:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021
结果还是一样!
使用 PRIORITY_LOW_POWER
与使用 PRIORITY_BALANCED_POWER_ACCURACY
的结果相同,因为 WiFi 状态似乎对坐标精度没有任何影响。
然后,为了涵盖所有基础,我改回 LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
,并将 AndroidManifest.xml 切换为 ACCESS_FINE_LOCATION
:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
第一次测试,没有 WiFi:
accuracy: 826.0 lat: 37.7825458 lon: -122.3948752
所以,它说准确度为 826 米,这是它在地图上的接近程度:
然后,我打开WiFi,结果如下:
accuracy: 18.847 lat: 37.779679 lon: -122.3930918
正如您在地图上看到的那样,它就在字面上:
似乎您在 Java 代码中的 LocationRequest
中使用什么并不重要,而您在 AndroidManifest.xml 中使用什么权限更重要,因为这里的结果清楚地显示使用 ACCESS_FINE_LOCATION
时,打开或关闭 WiFi 无线电会在准确性上产生巨大差异,而且总体上也更准确。
文档似乎有点误导,而且在使用 android.permission.ACCESS_COARSE_LOCATION
时,当您的应用程序是唯一一个使位置请求。
文档指出的另一件事是,使用 PRIORITY_BALANCED_POWER_ACCURACY
将使您的应用程序 "piggy-back" 进入其他应用程序发出的位置请求。
来自文档:
They will only be assigned power blame for the interval set by setInterval(long), but can still receive locations triggered by other applications at a rate up to setFastestInterval(long).
因此,如果用户打开 Google 地图,根据文档,您的应用可以获得此时更准确的位置。这是使用新的 Fused Location Provider 而不是旧 API 的主要优势之一,因为它可以减少应用程序的电池消耗量,而无需您做太多工作。
编辑:我对此功能进行了测试,看看使用 ACCESS_COARSE_LOCATION
.
第一次测试:ACCESS_COARSE_LOCATION
、PRIORITY_BALANCED_POWER_ACCURACY
,WiFi 开启:
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662
这让我在水中,离我现在的位置很远。 然后,我退出了测试应用程序,启动了 Google 地图,它准确地定位了我所在的位置,然后重新启动了测试应用程序。 测试应用程序无法从 Google 地图搭载到位置,结果与之前完全相同!
accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662
我重新测试了几次,只是为了确定,但看起来使用 ACCESS_COARSE_LOCATION
确实也禁用了应用程序 "piggy-back" 到其他应用程序获得的位置的能力。
看起来在 AndroidManifest.xml 中使用 ACCESS_COARSE_LOCATION
确实削弱了应用程序获取精确位置数据的能力。
总而言之,您唯一真正能做的就是磨练适合您和您的应用程序的最佳设置组合,希望此测试的结果可以帮助您做出决定。