美文网首页
Android动态权限

Android动态权限

作者: Aisen | 来源:发表于2018-07-14 01:42 被阅读137次

    Android的权限声明

    当APP需要访问APP沙箱外部数据或资源的区域,则需要声明权限。APP必须在AndroidManiffest文件中,通过<uses-permission>声明所需的权限。例如APP需要网络连接,则在manifest中添加一行

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.example.xxx">
    
        <uses-permission android:name="android.permission.INTERNET"/>
    
        <application ...>
            ...
        </application>
    </manifest>
    

    如果应用在manifest中列出了正常权限,系统会自动授予APP这些权限。

    如果应用在manifest中列出了危险权限,则需要用户明确同意授予这些权限。

    Android的权限分类

    Android权限分成几个保护级别,保护级别会影响是否需要APP运行时申请权限。

    目前分为三个保护级别:NormalSigatureDangerous权限。

    Normal权限在APP安装时系统自动授予。

    Sigature权限也是在APP安装时系统授予。

    Dangerous权限则需要在APP运行时,APP提示用户授予权限,即动态申请。

    1、Normal权限

    Normal权限不会直接给用户隐私权带来风险。如果APP在其manifest中声明Normal权限,则系统会在安装时自动授予APP该权限。系统不会提示用户授予Normal权限,用户也无法撤消这些权限。

    从Android 8.1(API 27)开始,以下权限为Normal:

    • 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
    • INSTALL_SHORTCUT
    • INTERNET
    • KILL_BACKGROUND_PROCESSES
    • MANAGE_OWN_CALLS
    • MODIFY_AUDIO_SETTINGS
    • NFC ……

    2、Sigature权限

    顾名思义,Sigature权限仅限于用该APK(定义了这个权限的APK)相同的私钥签名的应用才可以申请该权限。

    从Android 8.1(API 27)开始,以下权限为Signature:

    • BIND_ACCESSIBILITY_SERVICE
    • BIND_AUTOFILL_SERVICE
    • BIND_CARRIER_SERVICES
    • BIND_CHOOSER_TARGET_SERVICE
    • BIND_CONDITION_PROVIDER_SERVICE
    • BIND_DEVICE_ADMIN
    • BIND_DREAM_SERVICE
    • BIND_INCALL_SERVICE
    • BIND_INPUT_METHOD ……

    3、Dangerous权限

    Dangerous权限分成与设备功能相关的权限组,便于用户在授予权限时做出更有意义和更明智的选择。

    权限组 权限
    CALENDAR READ_CALENDAR
    - WRITE_CALENDAR
    CAMERA CAMERA
    CONTACTS CONTACTS
    - READ_CONTACTS
    - WRITE_CONTACTS
    - GET_ACCOUNTS
    LOCATION ACCESS_FINE_LOCATION
    - ACCESS_COARSE_LOCATION
    MICROPHONE RECORD_AUDIO
    PHONE READ_PHONE_STATE
    - READ_PHONE_NUMBERS
    - CALL_PHONE
    - ANSWER_PHONE_CALLS
    - READ_CALL_LOG
    - WRITE_CALL_LOG
    - ADD_VOICEMAIL
    - USE_SIP
    - PROCESS_OUTGOING_CALLS
    SENSORS BODY_SENSORS
    SMS SEND_SMS
    - RECEIVE_SMS
    - READ_SMS
    - RECEIVE_WAP_PUSH
    - RECEIVE_MMS
    STORAGE READ_EXTERNAL_STORAGE
    - WRITE_EXTERNAL_STORAGE

    运行时请求Dangerous权限

    • 如果设备运行的是Android 6.0(API 23)或更高版本,并且APP的targetSdkVersion为23或更高,则在安装时,不会通知用户任何APP权限。APP必须在运行时提示用户授予Dangerous权限。

    • 如果设备运行Android 5.1.1(API 22)或更低版本,或者targetSdkVersion为22或更低,则在安装时,系统会自动要求用户授予所有Dangerous权限。

    动态申请权限的关键代码

    1、请求需要的权限

    例如:检查APP是否具备摄像头权限Manifest.permission.CAMERA为例,并根据需要请求该权限

    // 检查权限,没有返回true,需要申请
    if (ContextCompat.checkSelfPermission(thisActivity,
                    Manifest.permission.CAMERA)
            != PackageManager.PERMISSION_GRANTED) {
    
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
                Manifest.permission.CAMERA)) {
                
            // 如果应用之前请求过此权限但用户拒绝了请求,此方法将返回true,这步判断非必须      
            // Show an expanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
    
        } else {
    
            // No explanation needed, we can request the permission.
    
            ActivityCompat.requestPermissions(thisActivity,
                    new String[]{Manifest.permission.CAMERA},
                    MY_PERMISSIONS_REQUEST_CAMERA);
    
            // MY_PERMISSIONS_REQUEST_CAMERA is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    }
    

    注:当APP调用requestPermissions()时,系统将向用户显示一个标准对话框。APP无法配置或更改此对话框。如果需要为用户提供任何信息或解释,应在调用requestPermissions()之前进行,如解释应用为什么需要权限中所述。

    2、处理权限请求响应

    当应用请求权限时,系统将向用户显示一个对话框。当用户响应时,系统将调用应用的onRequestPermissionsResult()方法,向其传递用户响应。因此,需要在Activity或者Fragment实现onRequestPermissionsResult方法。

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode,
            String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_CAMERA: {
                // If request is cancelled, the result arrays are empty.
                // 异常情况,grantResultsw也是空数组
                if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
    
                } else {
    
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }
    
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }
    

    其他

    为了方便申请动态权限,可以使用一些开源库,比如RxPermissions,将权限申请的代码requestPermissions()和请求结果的代码onRequestPermissionsResult()放在一起管理,避免了代码的分散,同时具备Rx(RxJava)的特性。

    使用如下

    private void requestPremission() {
        RxPermissions rxPermissions = new RxPermissions(this);
        rxPermissions.request(Manifest.permission.CAMERA)
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean granted) throws Exception {
                        if (granted) {
                            Log.d("zzhtest", "permission = " + granted);
                        } else {
                            Log.d("zzhtest", "permission = " + granted);
                        }
                    }
                });
    }
    

    参考

    相关文章

      网友评论

          本文标题:Android动态权限

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