美文网首页
Android 6.0 权限

Android 6.0 权限

作者: june5253 | 来源:发表于2016-08-30 14:57 被阅读146次

    在Android6.0之前,应用安装时系统会列出AndroidManifest清单上申请的所有权限,用户必须全部接受才能继续安装,并且这些权限授权之后无法撤销。这对于开发者来说是比较方便的,需要什么权限只需要在AndroidManifest申请即可,不需要考虑权限被拒绝等各种场景。但是对于用户来说却没有办法自主选择屏蔽他不想授予的权限,也容易给恶意程序利用。

    Android6.0之后,权限的申请由安装时变成了运行时。开发者仍然需要在AndroidManifest里面列出所需要的所有权限,但用户安装时不需要对这些权限进行授权,而是在运行时需要用到某个权限时才询问用户是否授权,用户可以选择接受或者拒绝。另外即使用户接受了,也可以在权限管理中进行撤销。如果直接使用用户没有授权的权限会导致crash,因此,开发时需要考虑这些场景,并作出处理。

    对于一些老的应用来说,也不用太担心,如果app的targetSdkVersion低于23,将继续使用旧有规则。看到这有人可能觉得干脆将所有的targetSdkVersion设置为23以下不就好了,也不用那么麻烦考虑权限的问题。但是要注意,在6.0的系统上,即使安装时取得了所有的权限,用户仍然可以之后在权限管理中撤销授权。因此,我们还是需要与时俱进,将targetSdkVersion升级到23并好好处理权限问题。

    Android的权限总的来说分为三种,分别是normal类型、dangerous类型和special类型:

    1、normal类型的权限不会威胁到用户的隐私,可以直接在AndroidManifest里面注册,在安装时就被授权,不需要每次使用时都检查权限,并且用户不能取消。主要包括:

    android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
    android.permission.ACCESS_NETWORK_STATE
    android.permission.ACCESS_NOTIFICATION_POLICY
    android.permission.ACCESS_WIFI_STATE
    android.permission.ACCESS_WIMAX_STATE
    android.permission.BLUETOOTH
    android.permission.BLUETOOTH_ADMIN
    android.permission.BROADCAST_STICKY
    android.permission.CHANGE_NETWORK_STATE
    android.permission.CHANGE_WIFI_MULTICAST_STATE
    android.permission.CHANGE_WIFI_STATE
    android.permission.CHANGE_WIMAX_STATE
    android.permission.DISABLE_KEYGUARD
    android.permission.EXPAND_STATUS_BAR
    android.permission.FLASHLIGHT
    android.permission.GET_ACCOUNTS
    android.permission.GET_PACKAGE_SIZE
    android.permission.INTERNET
    android.permission.KILL_BACKGROUND_PROCESSES
    android.permission.MODIFY_AUDIO_SETTINGS
    android.permission.NFC
    android.permission.READ_SYNC_SETTINGS
    android.permission.READ_SYNC_STATS
    android.permission.RECEIVE_BOOT_COMPLETED
    android.permission.REORDER_TASKS
    android.permission.REQUEST_INSTALL_PACKAGES
    android.permission.SET_TIME_ZONE
    android.permission.SET_WALLPAPER
    android.permission.SET_WALLPAPER_HINTS
    android.permission.SUBSCRIBED_FEEDS_READ
    android.permission.TRANSMIT_IR
    android.permission.USE_FINGERPRINT
    android.permission.VIBRATE
    android.permission.WAKE_LOCK
    android.permission.WRITE_SYNC_SETTINGS
    com.android.alarm.permission.SET_ALARM
    com.android.launcher.permission.INSTALL_SHORTCUT
    com.android.launcher.permission.UNINSTALL_SHORTCUT
    

    2、dangerous类型的权限可以直接访问用户的敏感数据,不仅需要在AndroidManifest里面注册,还需要在使用时请求授权。主要包括:



    可以看到dangerous类型的权限进行了分组,同一组的任何一个权限被授权了,其他权限也自动被授权。例如,一旦WRITE_CONTACTS被授权了,app也有READ_CONTACTS和GET_ACCOUNTS权限了。

    dangerous类型的权限申请主要调用这几个方法:

    Context.checkSelfPermission(String permission) 检查是否被授予了某个权限
    Activity.requestPermissions(String[] permissions, int requestCode) 申请一组权限
    Activity.onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 权限申请结果回调
    

    由于这些方法都是在api23引入的,所以需要在使用时先进行版本判断。下面以相机为例说明怎样申请权限:

    public void checkCameraPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 23及以后的版本需要检测权限
            int hasCameraPermission = checkSelfPermission(Manifest.permission.CAMERA);
            if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE_CAMERA);
            } else {
                cameraPermissionGranted(true);
            }
        } else {
            // 23之前的版本权限在安装时已经获取
            cameraPermissionGranted(true);
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE_CAMERA) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                cameraPermissionGranted(true);
            } else {
                cameraPermissionGranted(false);
            }
        }
    }
    

    另外,v4包中也提供了兼容方法ContextCompat.checkSelfPermission()和ActivityCompat.requestPermissions()可以避免版本判断,唯一的区别就是需要带上额外的参数Context或Activity,其他都一样:

    private void checkCameraPermission(Activity activity) {
        int hasCameraPermission = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
        if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE_CAMERA);
        } else {
            cameraPermissionGranted(true);
        }
    }
    

    权限的判断和申请其实比较简单,对于开发者来说更重要的其实是权限被接受或拒绝后的不同处理,也就是上面的cameraPermissionGranted(boolea granted)方法。比如如果你的应用必须使用相机,那么在相机权限申请拒绝后可以弹框提示用户,直到用户授权后才能进入使用界面。又或者应用并非必须使用相机,也可以从相册加载图片,那么当用户拒绝授权时,只需要禁掉相机部分的功能即可。

    3、special类型的权限包括WRITE_SETTINGS和SYSTEM_ALERT_WINDOW,Android单独制作了一个activity作为这两个权限的用户授权界面,必须通过指定intent,然后通过startActivity(intent)的方式来申请。
    special类型的权限申请主要用到以下几个方法:

    Settings.System.canWrite(Context context) 检查是否被授予了WRITE_SETTINGS权限
    Settings.canDrawOverlays(Context context) 检查是否被授予了SYSTEM_ALERT_WINDOW权限
    startActivityForResult(Intent intent, in requestCode) 打开用户授权界面
    onActivityResult(int requestCode, int resultCode, Intent data) 权限申请结果回调
    

    申请WRITE_SETTINGS权限的代码如下:

    public void checkWriteSettingsPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.System.canWrite(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, PERMISSION_REQUEST_CODE_WRITE_SETTINGS);
            } else {
                writeSettingsPermissionGranted(true);
            }
        } else {
            writeSettingsPermissionGranted(true);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PERMISSION_REQUEST_CODE_WRITE_SETTINGS) {
            // 判断是否有WRITE_SETTINGS权限
            if (Settings.System.canWrite(this)) {
                writeSettingsPermissionGranted(true);
            }else {
                writeSettingsPermissionGranted(false);
            }
        }
    }
    

    申请SYSTEM_ALERT_WINDOW的代码如下:

    public void checkSystemAlertWindowPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, PERMISSION_REQUEST_CODE_SYSTEM_ALERT_WINDOW);
            } else {
                systemAlertWindowPermissionGranted(true);
            }
        } else {
            systemAlertWindowPermissionGranted(true);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PERMISSION_REQUEST_CODE_SYSTEM_ALERT_WINDOW) {
            if (Settings.canDrawOverlays(this)) {
                systemAlertWindowPermissionGranted(true);
            } else {
                systemAlertWindowPermissionGranted(false);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Android 6.0 权限

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