权限:调用需要权限,用户可能会拒绝

Permission: Call requires permission which may be rejected by user

在 Android Studio 下编译时,我收到了此 post 标题中指定的警告。我尝试使用以下代码获取 GPS 更新:

    try {
        LocMgr = (LocationManager)getSystemService( LOCATION_SERVICE );
        LocMgr.requestLocationUpdates( K.GPS_PROVIDER, 0, 0, this );
        //LocMgr.addNmeaListener( this );   // NMEA
    }
    catch(Exception e) {
        UI.warningBox( this, "GPS appears to be either absent or disabled" );
    }

奇怪的是,我的应用程序在没有任何 run-time 许可请求的情况下仍然 工作正常。我做了但是在清单中请求权限。

    uses-permission  android:name="android.permission.ACCESS_FINE_LOCATION"
    uses-permission  android:name="android.permission.ACCESS_COARSE_LOCATION"

我并不不高兴,但我期待失败或至少是安全异常。

为什么 Android Studio 如此(出乎意料地)宽容?

顺便说一下,我模块的 gradle 脚本包括

    defaultConfig {
    applicationId "MY_APP_ID"
    minSdkVersion 11
    targetSdkVersion 26
    }

您 运行 您的应用程序使用的 android 是什么版本?在 marshmallow(api 级别 23)之前,您可以在不实际征求用户许可的情况下访问许多服务,例如 LocationService。

您甚至可以在不征求许可的情况下使用 wifi 和蓝牙。那时候是权限的狂野西部。从那以后这已经改变了,因为你的最高级别 api 可能会请求权限(你没有处理),这就是你收到警告

的原因

另外,如果您有权访问 google 服务,您应该改用 fusedlocationprovider,locationservice 在不创建服务以持续轮询它的情况下不会提供有效结果。

您的应用在 运行 时间内没有请求权限,因为您没有添加代码。此外,最近 Android 添加了 运行 时间权限(我猜是从 Android M 开始的)。

因此,在之前的 Android 版本中,您的应用将正常运行,因为您只需要将权限添加到清单中。

在新版本上,您必须在 运行 时额外请求权限。缺少权限并不总是会导致崩溃。它们只能在日志等方面生成警告。

无论如何,要消除该警告,您必须在 运行 时请求许可。下面,你可以找到一个小例子:

public class MainActivity extends AppCompatActivity implements LocationListener {

    private final static int LOCATION_PERMISSION_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ....

        try {
            LocMgr = (LocationManager) getSystemService(LOCATION_SERVICE);

            if (ActivityCompat.checkSelfPermission(this, permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED 
                  && ActivityCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // Missing both permissions. User didn't accept them yet. Request
                ActivityCompat.requestPermissions(this, new String[] {permission.ACCESS_FINE_LOCATION, permission.ACCESS_COARSE_LOCATION}, LOCATION_PERMISSION_CODE);
            } else {
                // Have permissions. Don't need to request. Just request location
                LocMgr.requestLocationUpdates( K.GPS_PROVIDER, 0, 0, this );
            }
        } catch(Exception e) {
            UI.warningBox( this, "GPS appears to be either absent or disabled" );
        }

        ....
    }

    @Override
    public void onRequestPermissionsResult(final int requestCode,
            @NonNull final String[] permissions,
            @NonNull final int[] grantResults) {
        if(requestCode == LOCATION_PERMISSION_CODE) {
            if(grantResults.length > 1
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED /* ACCESS_FINE_LOCATION */
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED /* ACCESS_COARSE_LOCATION */) {
                // User accepted both permissions. request location updates
                LocMgr.requestLocationUpdates( K.GPS_PROVIDER, 0, 0, this );
            }
        }
    }
}