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_ACCURACYACCESS_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_LOCATIONPRIORITY_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 确实削弱了应用程序获取精确位置数据的能力。

总而言之,您唯一真正能做的就是磨练适合您和您的应用程序的最佳设置组合,希望此测试的结果可以帮助您做出决定。