Android M之权限请求

Android M之权限请求

从Android Marshmallow开始,应用权限是在运行时获得的,而不是6.0之前的安装时获得,当然这是为用户的使用体验考虑,毕竟安装应用时一长串的权限说明看起来也是挺晕的(这是对于在Google Play商店下载安装应用而言,安装未知来源APK对于6.0和pre6.0都会在安装时看到一长串的权限说明)
当然也并不是说对与pre6.0的版本就没有用,用户是有可能在安装应用后限制应用的权限的(虽然原生的权限管理是Android M才开始加入的,不过很多定制系统都有加入权限管理功能,因此这也是需要考虑的),所以运行时的权限检查是有必要的,因此Google也提供了相对应的support包
本篇将对Android Support Library提供的权限请求功能,进行相应的学习和研究


权限分类

Android M对权限进行了分类。系统权限可以分为两种:一般的(normal)和危险的(dangerous)

normal permissions

那些可能需要访问数据和资源,但对用户的隐私的影响比较小的权限。如果应用已经在Android Manifest中声明了需要这些权限,系统会默认允许,而不会和用户交互。包含的权限有:

  • 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
  • MODIFY_AUDIO_SETTINGS
  • NFC
  • READ_SYNC_SETTINGS
  • READ_SYNC_STATS
  • RECEIVE_BOOT_COMPLETED
  • REORDER_TASKS
  • REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
  • REQUEST_INSTALL_PACKAGES
  • SET_ALARM
  • SET_TIME_ZONE
  • SET_WALLPAPER
  • SET_WALLPAPER_HINTS
  • TRANSMIT_IR
  • UNINSTALL_SHORTCUT
  • USE_FINGERPRINT
  • VIBRATE
  • WAKE_LOCK
  • WRITE_SYNC_SETTINGS

dangerous permissions

可能会访问用户隐私数据,修改用户和其他应用的数据的权限。危险的权限需要运行时进行请求

  • 权限分组
    任何一个危险权限都归属与一个权限分组。权限组有如下行为:

    1. 当应用请求一个权限,且该应用还未有该权限所在的权限组中的其他的权限时,请求权限所显示的对话框将会对该权限组进行描述,而不是这个权限
    2. 当应用请求一个权限,且该应用已经具有该权限所在的权限组中一个权限时,系统将会默认地允许该请求,而不会显式地让用户决定

    这些分组可能会在未来发生改变,所以不要太依赖权限分组,需要用到的权限还是要一个一个去检查和请求
    各个组别如下:

    组名权限
    CALENDARREAD_CALENDAR
    WRITE_CALENDAR
    CAMERACAMERA
    CONTACTSREAD_CONTACTS
    WRITE_CONTACTS
    GET_ACCOUNTS
    LOCATIONACCESS_FINE_LOCATION
    ACCESS_COARSE_LOCATION
    MICROPHONERECORD_AUDIO
    PHONEREAD_PHONE_STATE
    CALL_PHONE
    READ_CALL_LOG
    WRITE_CALL_LOG
    ADD_VOICEMAIL
    USE_SIP
    PROCESS_OUTGOING_CALLS
    SENSORSBODY_SENSORS
    SMSSEND_SMS
    RECEIVE_SMS
    READ_SMS
    RECEIVE_WAP_PUSH
    RECEIVE_MMS
    STORGEREAD_EXTERNAL_STORAGE
    WRITE_EXTERNAL_STORAGE

检查权限

在进行涉及危险权限的操作前,需要先检查应用是否具有对应的权限。建议总是在操作前检查权限,因为用户有可能会在设置面板取消对应的权限
调用ActivityCompat.checkSelfPermission()进行检查:

int isPermissionReady = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);

需要提供的参数是当前的上下文和对应的权限。android.Manifest.permission中定义了各个权限对应的标志
如果已经拥有该权限,则会返回PackageManager.PERMISSION_GRANTED,否则返回PackageManager.PERMISSION_DENIED


请求权限

解释为何需要这个权限

Android考虑到用户的体验,当用户拒绝了第一次的权限请求后,再次收到该权限请求时,对话框中会有一个“Don’t ask again”的checkbox,用户勾选了这个CB后将不会再收到这个权限的请求。那么开发者该如何知道呢?
ActivityCompat有一个方法shouldShowRequestPermissionRationale(),字面意思是“是否应该显示所请求权限的理由”,表示你是否需要对用户说明这个功能是怎样的,为何需要这个权限。如果用户已经拒绝了之前的请求,该方法会返回true;当用户拒绝了之前的请求并勾选了Don’t ask again”的checkbox,或者用户主动在权限管理中取消了该权限,则会返回false

请求权限

请求权限使用ActivityCompat.requestPermissions()方法,需要提供参数是上下文,权限标志数组,以及这次请求对应的请求码。
当然权限的请求必须是异步的,因为从显示对话框,再到用户对对话框做出选择都是需要时间的,requestPermissions()会立即返回,至于请求的结果则会在回掉函数中体现(下面讲)
结合上面的内容,一次请求应该这么写:

private void readContacts() {
    if (Activity.checkSelfPermission(this, 
            Manifest.permission.READ_CONTACTS) !=
        PackageManager.PERMISSION_GRANTED) {

        //如果没有该权限,进行请求
        requestReadContactsPermission();
    } else {

        //进行联系人读取
    }
}

private void requestReadContactsPermission() {
    if (ActivityCompat.shouldShowRequestPermissionRationale(this,
               Manifest.permission.READ_CONTACTS)) {

        //进行相应的解释。要注意必须是异步的,不要阻塞主线程

    } else {
        //直接请求
        ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            REQUEST_READ_CONTACTS};
    }
}

处理请求结果

由于权限请求是异步的,因此请求结果将会以回调的形式返回,ActivityCompat类中有一个回调接口OnRequestPermissionsResultCallback,因此请求代码所处的Activity需要实现这个接口
这个接口中只有一个方法:

onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

参数依次是你的请求所设置的请求码,权限列表,以及每个权限对应的请求结果
具体实现可以这么写:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], 
    @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_READ_CONTACTS:
            if (grantResults.length > 0 && grantResults[0] 
                == PackageManager.PERMISSION_GRANTED) {

                //获得权限,继续对应的操作
                readContacts();
            } else {

                //未能获得权限,取消该操作但不要让应用退出
            }
            break;
        //...
    }
}

参数中的权限数组和结果数组是一一对应的。根据请求码判断是哪个请求,并对各个权限进行检查


何时请求权限

根据Android Developer的介绍,权限请求的情况有两个因素:权限的重要性,以及用户对权限必要性的认识
讲权限的重要性分为重要的(critical)和次要的(secondary),用户的认识分为清除的(clear)和不清楚的(unclear)。对于一款相机应用来说,可以有如下四种情况:
1. 如果该权限对应用来说很重要,而且用户也很清楚,例如CAMERA权限。直接启动时请求权限,不需要多余地说明
2. 如果该权限对应用来说很重要,但用户不能马上认识到其必要,例如记录相片地理位置的功能。对于这种很吸引人的功能,或者是更新后加入的新特性,可以在用户教程(tutorial)界面时进行介绍,然后再请求权限
3. 如果该权限是比较次要的,但用户很清楚权限的必要,例如给相片加入语音。对于这种功能,当用户点击使用,直接在上下文种请求权限就行了
4. 如果该权限是比较次要的,而且用户不能马上认识到其必要,例如读取短信中的验证码。自动读取短信中的验证码是有用的,但用户有时并不能马上认识到它的便利,这样的话可以在上下文中适当地说明这个功能,当用户启动该功能时再请求权限
引用官方的说明图:


关于Android M的权限请求大概就是这么多。从官方的说明文档可以看出来,权限请求这个改动其实是充满了设计感的,无论是请求策略,还是请求代码,都体现了Android在用户体验,以及帮助开发者开发更优质的应用,所做出的努力。谷歌在优质化应用上所做的其实并不止是Material Design,很多小细节都在大大地改变Android应用在人们心中的印象。

另附:
官方说明文档
android-RuntimePermissions

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio中获取相机权限的方法有两种。第一种是在应用启动时就直接获取所需的权限,第二种是在使用相机功能时才获取权限。 第一种方法是在应用的初始化过程中获取权限。你可以在MainActivity的onCreate方法中添加以下代码来获取相机权限: ``` int permissioncamera; int permissionaudio; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { permissioncamera = MainActivity.this.checkSelfPermission(android.Manifest.permission.CAMERA); permissionaudio = MainActivity.this.checkSelfPermission(android.Manifest.permission.RECORD_AUDIO); } else { permissioncamera = PermissionChecker.checkSelfPermission(MainActivity.this, android.Manifest.permission.CAMERA); permissionaudio = PermissionChecker.checkSelfPermission(MainActivity.this, android.Manifest.permission.RECORD_AUDIO); } if (permissioncamera != PackageManager.PERMISSION_GRANTED) { // 请求相机权限 } if (permissionaudio != PackageManager.PERMISSION_GRANTED) { // 请求录音权限 } ``` 这段代码会根据当前设备的Android版本来判断使用哪种方式获取权限。 第二种方法是在使用相机功能时才获取权限。你需要在AndroidManifest.xml文件中添加以下权限: ``` <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ``` 然后,在你需要使用相机的地方,通过代码来请求相机权限。 请注意,为了保证应用的正常运行,你需要在AndroidManifest.xml文件中添加相应的权限声明,并在代码中进行权限检查和请求。 #### 引用[.reference_title] - *1* *3* [Unity与Android Studio交互之 ✨ 获取手机权限(存储、录音、相机等)](https://blog.csdn.net/weixin_41716049/article/details/119318207)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Android studio 申请读写权限,相机权限。](https://blog.csdn.net/qq_29220369/article/details/118306703)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值