美文网首页
Android-6.0 棉花糖权限的那点事

Android-6.0 棉花糖权限的那点事

作者: ztzt123 | 来源:发表于2018-03-02 10:44 被阅读0次

    Android6.0引入了全新的权限管理方式,也就是运行时权限,至于什么是运行时权限,我们先看一下6.0以前的权限处理。

    6.0以前的权限

    6.0以前的系统,我们在安装一个应用的时候会默认赋予所有权限。

    pre-marshmallow-permission.jpg

    安装的时候会提示应用需要获取的所有权限,选择安装则会全部获取,如果要拒绝获取权限,只能放弃安装应用。用户无法选择获取或者放弃某些权限。

    6.0的运行时权限

    什么是运行时权限?举个栗子,以某个需要拍照的应用为例,当运行时权限生效时,其Camera权限不是在安装后赋予,而是在应用运行的时候进行请求权限(比如当用户按下”相机拍照“按钮后)看到的效果则是这样的,提示用户需要权限,用户选择允许,才能获取到该权限。

    marshmallow-permission.png

    一个问题:我们必须要支持运行时权限吗?

    如果我们不想启用运行时权限其实很简单,我们只要,把targetSdkVersion设置为设置低于23就可以了,系统会认为我们的应用还不支持新特性,会按照棉花糖以前的版本进行处理。这样的处理不会有任何的问题,但有一点,棉花糖对每一个应用都有一个权限管理界面,是这样

    6a195423jw1ezwqnmjhcdj20u01hc40k.jpg

    如果用户手动关闭了我们应用的某些权限,问题就出现了,运行应用时可能会出现崩溃。下面这个例子

    TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
    String deviceId = telephonyManager.getDeviceId();
    if (deviceId.equals(mLastDeviceId)) {//This may cause NPE
    //do something
    }

    如果用户撤消了获取DeviceId的权限,那么再次运行时,deviceId就是null,如果程序后续处理不当,就会出现崩溃。所以说该来的还是要来的,我们需要处理好运行时权限问题。

    权限分类

    android系统的权限很多但不是所有的权限都是敏感权限,棉花糖将android系统权限分为四类。

    1.正常权限(Normal Protection)

    2.危险权限(Dangerous)

    3.特殊权限(Particular)

    4.其他权限(几乎使用不到)

    1.正常权限

    这一类权限是对用户隐私影响较小,没有什么安全问题,这类权限会像6.0以前的系统一样,安装就获取到这些权限,没有用户提醒,也不能被取消。下面是正常权限列表。

    ACCESS_LOCATION_EXTRA_COMMANDS
    ACCESS_NETWORK_STATE
    ACCESS_NOTIFICATION_POLICY
    ACCESS_WIFI_STATE
    BLUETOOTH
    BLUETOOTH_ADMIN
    BROADCAST_STICKY
    CHANGE_NETWORK_STATE
    CHANGE_WIFI_MULTICAST_STATE
    CHANGE_WIFI_STATE
    DISABLE_KEYGUARD
    EXPAND_STATUS_BAR
    GET_PACKAGE_SIZE
    INTERNET
    KILL_BACKGROUND_PROCESSES
    MODIFY_AUDIO_SETTINGS
    NFC
    READ_SYNC_SETTINGS
    READ_SYNC_STATS
    RECEIVE_BOOT_COMPLETED
    REORDER_TASKS
    REQUEST_INSTALL_PACKAGES
    SET_TIME_ZONE
    SET_WALLPAPER
    SET_WALLPAPER_HINTS
    TRANSMIT_IR
    USE_FINGERPRINT
    VIBRATE
    WAKE_LOCK
    WRITE_SYNC_SETTINGS
    SET_ALARM
    INSTALL_SHORTCUT
    UNINSTALL_SHORTCUT

    对于这些权限,我们只需要在Manifest中指定,应用安装就会获取。

    2.危险权限

    危险权限才是运行时权限的主要处理对象,这些权限可能会有隐私问题,或者影响其他应用的运行,危险权限可以分为以下几组:

    • CALENDAR
    • CAMERA
    • CONTACTS
    • LOCATION
    • MICROPHONE
    • PHONE
    • SENSORS
    • SMS
    • STORAGE

    对于各组权限对应的具体权限如下:

    6a195423jw1ezwpc11cs0j20hr0majwm.jpg

    关于权限我们需要下面几个API

    • int checkSelfPermission(String permission) 用来检测应用是否已经具有权限
    • void requestPermissions(String[] permissions, int requestCode) 进行请求单个或多个权限
    • void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

    请求Camera的权限

    private static final int REQUEST_PERMISSION_CAMERA_CODE = 1;
    @Override
    public void onClick(View v) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (!(checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
    if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
    Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
    }
    requestCameraPermission();
    }
    }
    }
    private void requestCameraPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA_CODE);
    }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSION_CAMERA_CODE) {
    int grantResult = grantResults[0];
    boolean granted = grantResult == PackageManager.PERMISSION_GRANTED;
    Log.i(LOGTAG, "onRequestPermissionsResult granted=" + granted);
    }
    }

    通常情况下,我们会得到这样的一个对话框

    marshmallow-permission.png

    我们可以在onRequestPermissionsResult中获取用户的选择情况进行相应的处理。但如果用户选择了否,我们再次申请的时候就会多一个checkbox

    6a195423jw1ezwtz1ljjgj20u01hcad8.jpg

    如果用户选择了不在询问,然后拒绝,我们的应用基本上就获取不到这个权限了,shouldShowRequestPermissionRationale这个API可以帮我们判断接下来的对话框是否包含”不再询问“选择框,我们可以这样使用。这样如果我们第一次申请权限失败后,在申请权限的时候就会弹出提示Toast,这个使用一定要向用户说明我们为什么要申请这个权限,来做什么。

    if (!(checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED)) {
    if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
    Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
    }
    requestReadContactsPermission();
    } else {
    Log.i(LOGTAG, "onClick granted");
    }

    对于同时申请多个权限我们可以

    String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE};
    requestPermissions(permissions, REQUEST_CODE);

    效果是这样,同时申请多个权限可以避免弹出多个对话框造成不好的视觉影响。

    6a195423jw1ezxulzbeu2j20iq0ggt9y.jpg

    3.特殊权限

    特殊权限是指特别敏感的权限,这里主要是指两个。

    SYSTEM_ALERT_WINDOW,设置悬浮窗

    WRITE_SETTINGS 修改系统设置

    关于上面两个特殊权限的授权,做法是使用startActivityForResult启动授权界面来完成,下面是请求SYSTEM_ALERT_WINDOW权限。

    private static final int REQUEST_CODE = 1;
    private void requestAlertWindowPermission() {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
    intent.setData(Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (Settings.canDrawOverlays(this)) {
    Log.i("AlertWindowPermission", "onActivityResult granted");
    }
    }
    }
    }

    需要注意:

    • 使用Action Settings.ACTION_MANAGE_OVERLAY_PERMISSION启动隐式Intent
    • 使用"package:" + getPackageName()携带App的包名信息
    • 使用Settings.canDrawOverlays方法判断授权结果

    WRITE_SETTINGS 使用的则是 Action Settings.ACTION_MANAGE_WRITE_SETTINGS,使用Settings.System.canWrite方法检测授权结果

    相关文章

      网友评论

          本文标题:Android-6.0 棉花糖权限的那点事

          本文链接:https://www.haomeiwen.com/subject/fkooxftx.html