ACCESS_COARSE_LOCATION 权限可在 Android 上提供信号塔精度 [英] ACCESS_COARSE_LOCATION permission gives a cell tower precision on Android

查看:98
本文介绍了ACCESS_COARSE_LOCATION 权限可在 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 会使用 WiFi,因为文档就是这么说的.

ACCESS_COARSE_LOCATION 的文档说明:

<块引用>

允许应用访问来自网络的大致位置位置来源,例如手机信号塔和 Wi-Fi.

所以,我进行了测试,结果令人惊讶.

这是我用来测试的代码:

公共类 MainActivity 扩展 Activity 实现GoogleApiClient.ConnectionCallbacks、GoogleApiClient.OnConnectionFailedListener、LocationListener {LocationRequest mLocationRequest;GoogleApiClient mGoogleApiClient;@覆盖protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);buildGoogleApiClient();mGoogleApiClient.connect();}@覆盖受保护的无效 onPause(){super.onPause();如果(mGoogleApiClient != null){LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);}}受保护的同步无效 buildGoogleApiClient() {Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show();mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).建造();}@覆盖公共无效onConnected(捆绑包){Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show();mLlocationRequest = 新位置请求();mLlocationRequest.setInterval(10);mLocationRequest.setFastestInterval(10);mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);//mLlocationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);//mLlocationRequest.setSmallestDisplacement(0.1F);LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);}@覆盖公共无效 onConnectionSuspended(int i) {Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();}@覆盖public void onConnectionFailed(ConnectionResult connectionResult) {Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();}@覆盖公共无效onLocationChanged(位置位置){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:

编译'com.google.android.gms:play-services:7.3.0'

我做的第一个测试是使用 PRIORITY_BALANCED_POWER_ACCURACY,没有 WiFi.请注意,我还禁用了 Always Allow Scanning,因为它指出:

<块引用>

让 Google 定位服务和其他应用程序扫描 Wi-Fi网络,即使 Wi-Fi 关闭

所以,如果启用它肯定会影响结果.

请注意,我还在所有测试中将定位模式设置为省电模式,因此 GPS 无线电一直处于关闭状态.

以下是 PRIORITY_BALANCED_POWER_ACCURACYACCESS_COARSE_LOCATION 和没有 WiFi 的结果:

准确度:2000.0 纬度:37.78378378378378 经度:-122.40320943772021

所以,它说 2000 米精度,这是实际坐标有多远,绿色箭头显示我的实际位置:

然后,我开启了WiFi,再次运行测试,结果竟然完全一样!

准确度:2000.0 纬度:37.78378378378378 经度:-122.40320943772021

然后,我切换到 LocationRequest 中的 LocationRequest.PRIORITY_LOW_POWER,同时将 android.permission.ACCESS_COARSE_LOCATION 保留在 AndroidManifest.xml 中.>

没有无线网络:

准确度:2000.0 纬度:37.78378378378378 经度:-122.40320943772021

有无线网络:

准确度:2000.0 纬度:37.78378378378378 经度:-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:

准确度:826.0 纬度:37.7825458 经度:-122.3948752

所以,它说精度为 826 米,这是它在地图上的接近程度:

然后,我打开了 WiFi,结果如下:

准确度:18.847 纬度:37.779679 经度:-122.3930918

正如你在地图上看到的那样:

在Java代码中的LocationRequest中使用什么似乎不重要,而在AndroidManifest.xml中使用什么权限更重要,因为这里的结果清楚地表明使用ACCESS_FINE_LOCATION,打开或关闭 WiFi 无线电对准确性有很大影响,而且总体上也更准确.

看起来文档似乎有点误导,而且在使用 android.permission.ACCESS_COARSE_LOCATION 时,打开或关闭 WiFi 无线电在您的应用程序中没有任何区别是唯一一个发出位置请求的人.

文档说明的另一件事是,使用 PRIORITY_BALANCED_POWER_ACCURACY 将使您的应用捎带"到其他应用发出的位置请求上.来自文档:

<块引用>

他们只会在设定的时间间隔内被分配权力责备setInterval(long), 但仍然可以接收其他触发的位置以高达 setFastestInterval(long) 的速率应用.

因此,如果用户打开 Google 地图,根据文档,您的应用程序可以获得更准确的位置.这是使用新的 Fused Location Provider 而不是旧 API 的主要优点之一,因为它减少了应用程序的电池消耗量,而您无需做太多工作.

我对此功能进行了测试,以了解使用 ACCESS_COARSE_LOCATION 时会发生什么.

第一次测试:ACCESS_COARSE_LOCATIONPRIORITY_BALANCED_POWER_ACCURACY 和 WiFi:

准确度:2000.0 纬度:37.78378378378378 经度:-122.38041129850662

这让我掉进了水里,离我现在的位置很远.然后,我退出了测试应用程序,启动了谷歌地图,它准确地定位了我所在的位置,然后重新启动了测试应用程序.测试应用无法搭载 Google 地图中的位置,结果与之前完全相同!

准确度:2000.0 纬度:37.78378378378378 经度:-122.38041129850662

我重新测试了几次,只是为了确定,但看起来确实使用 ACCESS_COARSE_LOCATION 也禁用了应用程序捎带"到其他应用程序获得的位置的能力.

看起来在 AndroidManifest.xml 中使用 ACCESS_COARSE_LOCATION 在获取精确位置数据方面确实削弱了应用程序.

总而言之,您真正能做的唯一一件事就是寻找适合您和您的应用的最佳设置组合,希望此测试的结果可以帮助您做出决定.

I am making some tests with the requestLocationUpdates() function from the FusedLocationApi. I am using the PRIORITY_BALANCED_POWER_ACCURACY. A city block precision is fine for me.

When I request the ACCESS_FINE_LOCATION permission, I get around a 100m precision which is great with GPS off. As I do not need a GPS precision but a city block precision, I would like to request only the ACCESS_COARSE_LOCATION permission. However when I request the ACCESS_COARSE_LOCATION permission, I get a 2 km precision. It seems that the device does not use anymore the Wifi permission and only a cell tower precision.

How can I have a better precision with the ACCESS_COARSE_LOCATION permission?

Note: the GPS is disabled on my test device.

解决方案

This is an interesting problem, and I was under the impression that using ACCESS_COARSE_LOCATION would use WiFi, since that's what the documentation says.

The documentation for ACCESS_COARSE_LOCATION states:

Allows an app to access approximate location derived from network location sources such as cell towers and Wi-Fi.

So, I put it to the test, and the results are surprising.

Here is the code that I used to test with:

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'

The first test I did was with PRIORITY_BALANCED_POWER_ACCURACY, and no WiFi. Note that I also disabled Always Allow Scanning, since it states:

Let Google Location Service and other applications scan for Wi-Fi networks, even when Wi-Fi is off

So, that would certainly skew the results if it was enabled.

Note that I also had Location Mode set in Battery Saving Mode for all tests, so the GPS radio was off the entire time.

Here are the results of PRIORITY_BALANCED_POWER_ACCURACY, ACCESS_COARSE_LOCATION, and no WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

So, it says 2000 meter accuracy, and here is how far away the actual coordinates are, the green arrow shows where I actually am:

Then, I enabled WiFi, and ran the test again, and surprisingly, the results were exactly the same!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

Then, I switched to LocationRequest.PRIORITY_LOW_POWER in the LocationRequest while keeping android.permission.ACCESS_COARSE_LOCATION in the AndroidManifest.xml.

No WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

With WiFi:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.40320943772021

The results were exactly the same again! Using PRIORITY_LOW_POWER had the same results as using PRIORITY_BALANCED_POWER_ACCURACY, in that the WiFi state did not seem to have any effect on accuracy of coordinates.

Then, just to cover all the bases, I changed back to LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY, and switched the AndroidManifest.xml to ACCESS_FINE_LOCATION :

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

First test, no WiFi:

accuracy: 826.0 lat: 37.7825458 lon: -122.3948752

So, it says accuracy of 826 meters, and here is how close it was on the map:

Then, I powered on WiFi, and here is the result:

accuracy: 18.847 lat: 37.779679 lon: -122.3930918

It's literally spot on, as you can see on the map:

It seems that it matters less what you use in your LocationRequest in the Java code, and more what permission you use in the AndroidManifest.xml, since the results here clearly show that when using ACCESS_FINE_LOCATION, having the WiFi radio on or off made a huge difference in the accuracy, and it was also more accurate in general.

It certainly seems as though the documentation is a bit miss-leading, and that while using android.permission.ACCESS_COARSE_LOCATION, having the WiFi radio on or off doesn't make a difference when your app is the only one making location requests.

Another thing that the documentation states is that using PRIORITY_BALANCED_POWER_ACCURACY will let your app "piggy-back" onto location requests made by other apps. From the documentation:

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).

So if the user opens up Google Maps, according to the documentation your app can obtain a more accurate location at that point. That is one of the major up-sides of using the new Fused Location Provider rather than the older APIs, since it decreases the amount of battery drain of your app without much work on your part.

Edit: I performed a test of this functionality, to see what would happen while using ACCESS_COARSE_LOCATION.

First Test: ACCESS_COARSE_LOCATION, PRIORITY_BALANCED_POWER_ACCURACY, and WiFi on:

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662

That placed me out in the water, quite far from my current location. Then, I exited the test app, launched Google Maps, which located me exactly where I am, then re-launched the test app. The test app was not able to piggy-back onto the location from Google Maps, and the result was exactly the same as before!

accuracy: 2000.0 lat: 37.78378378378378 lon: -122.38041129850662

I re-tested this a few times, just to be sure, but it really looks like using ACCESS_COARSE_LOCATION also disables the ability of apps to "piggy-back" on to locations obtained by other apps.

It looks like using ACCESS_COARSE_LOCATION in the AndroidManifest.xml really cripples the app in terms of getting precise location data.

In conclusion, the only thing you can really do is hone in on the best combination of settings that work for you and your app, and hopefully the results of this test can help you make that decision.

这篇关于ACCESS_COARSE_LOCATION 权限可在 Android 上提供信号塔精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆