资讯专栏INFORMATION COLUMN

Android运行时权限的总结,以及EasyPermissions框架的使用

whatsns / 3633人阅读

摘要:第三个参数这次请求权限的唯一标识请求码,。申请如果失败了,这时候有个方法出现了这个方法是谷歌建议的。系统只会授予应用明确请求的权限。然而一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。

1、android6.0以后的危险权限介绍

(注意:Android O 8.0对于权限更加严格,下面会说一下8.0)
android6.0以后有些危险权限需要手动去授权,就有了运行时权限的处理。下面的表格就是危险权限组:

权限组名 权限名
CALENDAR 日历 READ_CALENDAR
WRITE_CALENDER
CAMERA 相机 CAMERA
CONTACTS 联系人 READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION 定位 ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE 麦克风 RECORD_AUDIO
PHONE 电话 READ_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORS 传感器 BODY_SENSORS
SMS 短信 Short Message Service
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE 数据存储 READ_EXTRAL_STRORAGE
WRITE_EXTERNAL_STORAGE

申请权限时:
1、在清单文件中声明权限(如果不在这张表中,声明完就可以了)
2、如果在这张表中的权限需要手动来申请

这些权限6.0以后需要手动申请,,每一个权限组中的权限只要有一个权限同意授权了,整个权限组中的权限就不用重复申请了。
如果如果查看所有的权限,请参考:https://segmentfault.com/a/11...

2、运行时权限申请过程:

传统的申请过程是:
1、在AndroidManifest文件中添加需要的权限。
2、检查权限是否授权
3、申请权限
4、处理授权的结果

一步步来:
1、首先在请单文件中声明,这个不用说
2、检查权限是否授权

if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {
    //没有授权,编写申请权限代码
}else{
//已经授权,执行操作代码
}    

基本上调用checkSelfPermission()函数传入权限参数,返回的结果又两个:
如果是已授权的权限,该方法返回结果是 PackageManager.PERMISSION_GRANTED 常量为 0,
如果是未授权的权限,该方法返回结果是 PackageManager.PERMISSION_DENIED 常量为 -1。
这样就可以判断是否已经授权,来进行下一步的操作。

3、如果没有授权,需要申请权限

ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            MY_PERMISSIONS_REQUEST_READ_CONTACTS);

这是一个异步的方法,第一个参数是Context;第二个参数是需要申请的权限的字符串数组(这个是支持同时申请多个权限,系统会逐个询问是否授权);第三个参数为请求码requestCode,主要用于回调的时候检测。

4、处理权限申请的回调结果
重写Activity或者fragment的 onRequestPermissionsResul()方法

  //权限回调方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    switch (requestCode){

        case 0:
            //grantResults数组存储的申请的返回结果,
            //PERMISSION_GRANTED 表示申请成功
            if (grantResults.length>0&&grantResults[0]== PackageManager.PERMISSION_GRANTED){
                //授权成功,
                //这里写相应的 操作代码
            }else{
                //授权失败,可以简单提示用户
                Toast.makeText(this, "没有授权继续操作", Toast.LENGTH_SHORT).show();

            }
            break;
        case 1:
            //同上
            break;
        default:
            break;
    }
}
这里稍微说一下,申请的时候是一个一个的申请的话,每次申请都有一个请求码,
这里的grantResults数组就只有一个值,所以都是grantResults[0]来和
PERMISSION_GRANTED来进行比较
如果是一次申请多个权限,grantResults数组返回的值就不止一个,但是,直接遍历
它就行,只要全部满足条件才算申请成功,才能进行相应的操作
一般的写法是:通过
if判断权限是否申请,没有申请,把它加到一个集合里面,把所有的权限都判断一遍
以后,去遍历这个集合,只要有一个没有申请的,就需、要去申请权限,   
 把这个集合转为数组,传到requestPermissions的第二个参数,然后就处理相应
 结果就可以了,遍历grantResults数组,判断是不是全部满足条件
 
 
3、EasyPermissions的使用

GitHub地址:https://github.com/googlesamp...
EasyPermissions是谷歌封装的一个运行时权限申请的库,简化了操作的过程。
使用过程: 没有什么先后顺序,下面没有按这个顺序。这么做是可以的,当然还有其他的使用方法

1、builde gradle中依赖
2、清单文件中声明权限
3、重写onRequestPermissionsResult()方法,把执行操作给easyPermissions来
4、通过hasPermissions检查权限,或者原生的也行,然后去申请权限
5、实现EasyPermissions.PermissionCallbacks接口,重写两个方法,成功或失败
6、在成功或者失败方法中编写要具体做的事。

GitHub地址:
(1)依赖库

dependencies {
    compile "pub.devrel:easypermissions:1.0.1"
}

(2)再在清单文件中声明要申请的危险权限
如果不声明的话,直接在代码中写也能申请成功,但是好想不会弹出询问框,直接就申请了

(3)申请权限
可以直接申请

EasyPermissions.requestPermissions(
                    MainActivity.this,
                    "申请权限",
                    0,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.RECORD_AUDIO);

最好还是检查一下权限是否申请:
EasyPermissions.hasPermissions(Context context, @NonNull String… perms)方法来检测一个或者多个权限是否被允许,第二个参数是个可变数组,可以申请多个

String[] perms = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};
if (EasyPermissions.hasPermissions(this, perms)) {
    
    // 已经申请过权限,做想做的事
} else {
    // 没有申请过权限,现在去申请
    EasyPermissions.requestPermissions(this, getString(R.string.camera_and_location_rationale),
            RC_CAMERA_AND_LOCATION, perms);
}
                    

下面来说一个申请权限这个方法:
EasyPermissions.requestPermissions():

requestPermissions() 一般用这个四个参数的就可以
第一个参数:Context对象
第二个参数:权限弹窗上的文字提示语。告诉用户,这个权限用途。
第三个参数:这次请求权限的唯一标识请求码,code。
第四个参数 : 一些系列的权限。
这里说一下第二个参数,不是第一次申请系统默认弹出的提示语,而是,我们拒绝后,再次点击申请弹出的对话框,,显示我们设置的提示语,下面有两个按钮,确认和取消,我就不贴图了。

还有六个参数的,多了两个参数就是,修改我们上面那个确认和取消的字样,你可以干成yes 和no.

4、重写onRequestPermissionsResult()方法,把执行操作给easyPermissions
一行代码就搞定了

 @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

5、实现EasyPermissions.PermissionCallbacks接口,重写两个方法

public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    // 把执行结果的操作给EasyPermissions
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}

@Override //申请成功时调用
public void onPermissionsGranted(int requestCode, List list) {
    //请求成功执行相应的操作
    
    比如,举个例子
    switch (requestCode){
        case 0:
            Toast.makeText(this, "已获取WRITE_EXTERNAL_STORAGE权限", Toast.LENGTH_SHORT).show();
            break;
        case 1:
            Toast.makeText(this, "已获取WRITE_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限", Toast.LENGTH_SHORT).show();
            break;
    }
}

@Override //申请失败时调用
public void onPermissionsDenied(int requestCode, List list) {
    // 请求失败,执行相应操作
    
}
}

接下来就要说一下成功或者失败后的操作了: 申请成功就直接做该做的事就行了,没啥。
申请如果失败了,这时候有个方法出现了EasyPermissions.somePermissionPermanentlyDenied(this, perms)
这个方法是谷歌建议的。就是在我们点了不在询问并拒绝,会弹出对话框,告诉用户这个权限时干嘛的,很重要,建议不要拒绝哈哈
比如这样:

@Override
public void onPermissionsDenied(int requestCode, List perms) {

if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
    new AppSettingsDialog.Builder(this).build().show();
    //弹出个对话框
}

}

当然我们可以定制一下这个对话框:

@Override
public void onPermissionsDenied(int requestCode, List perms) {
    //处理权限名字字符串
    StringBuffer sb = new StringBuffer();
    for (String str : perms){
        sb.append(str);
        sb.append("
");
    }
    sb.replace(sb.length() - 2,sb.length(),"");

    switch (requestCode){
        case 0:
            Toast.makeText(this, "已拒绝权限" + perms.get(0), Toast.LENGTH_SHORT).show();
            break;
        case 1:
            Toast.makeText(this, "已拒绝WRITE_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限"+ perms.get(0), Toast.LENGTH_SHORT).show();
            break;
    }
    if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
        Toast.makeText(this, "已拒绝权限" + sb + "并不再询问" , Toast.LENGTH_SHORT).show();
        new AppSettingsDialog
                .Builder(this)
                .setRationale("此功能需要" + sb + "权限,否则无法正常使用,是否打开设置")
                .setPositiveButton("是")
                .setNegativeButton("否")
                .build()
                .show();
    }
}

6、(可选)@AfterPermissionGranted()注解

使用 AfterPermissioonGranted 注解。这是可选的,但是提供出来是为了方便。如果所有的请求的权限都被授予了,被注解的方法将会被执行,这样做是为了简化通常的请求权限成功之后再调用方法的流程。同时也可以在onPermissionsGranted 的回调中添加逻辑操作:
比如官网上的这个实例代码:
这里的方法名可以自己取,主要是权限都申请完,就调用这个方法,执行里面的操作。
其实就相当于在onPermissionsGranted()调用这个方法而已:

@AfterPermissionGranted(RC_CAMERA_AND_LOCATION)
private void methodRequiresTwoPermission() {
String[] perms = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};
if (EasyPermissions.hasPermissions(this, perms)) {
    // Already have permission, do the thing
    // ...
} else {
    // Do not have permissions, request them now
    EasyPermissions.requestPermissions(this, getString(R.string.camera_and_location_rationale),
            RC_CAMERA_AND_LOCATION, perms);
}
}

基本上介绍完了

4、android 8.0运行时权限

对于针对Android O的应用,此行为已被纠正。系统只会授予应用明确请求的权限。然而一旦用户为应用授予某个权限,则所有后续对该权限组中权限的请求都将被自动批准。

例如,假设某个应用在其清单中列出READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE。应用请求READ_EXTERNAL_STORAGE,并且用户授予了该权限,如果该应用针对的是API级别24或更低级别,系统还会同时授予WRITE_EXTERNAL_STORAGE,因为该权限也属于STORAGE权限组并且也在清单中注册过。如果该应用针对的是Android O,则系统此时仅会授予READ_EXTERNAL_STORAGE,不过在该应用以后申请WRITE_EXTERNAL_STORAGE权限时,系统会立即授予该权限,而不会提示用户。
注意:如果使用了没有授权的权限,会崩溃的

所以对于8.0权限,我们要做的处理,是尽量把所用到的危险权限全部申请。但是有的权限在不同版本出现,所以要兼容不同的版本,所以要加一个版本的判断。

归根结底:android M (6.0)以后,申请权限组一个,即表示整个权限组可以用,所以我们干脆,只要api 版本大于23(6.0),我们申请的权限就是申请整个权限组。这样就兼容了android8.0-------------------为了省事的话可以用AndPermission这个第三方框架,或者自己封装一个。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14073.html

相关文章

  • Android优雅地申请动态权限

    摘要:是权限被拒绝,但是没有勾选不再提醒。这样被拒绝后再次申请权限是不会弹框提醒的。用户点击拒绝,并勾选不再提示,下次请求权限时,系统弹窗不会再出现,而且为,此时你的权限申请被用户彻底拒绝,需要跳转到系统设置页手动允许权限。 版权声明:本文已授权微信公众号:Android必修课,转载请申明出处Android6.0以上的系统中,引入了运行时权限检查,运行时权限分为正常权限和危险权限,当我们的...

    nicercode 评论0 收藏0
  • Android优雅地申请动态权限

    摘要:是权限被拒绝,但是没有勾选不再提醒。这样被拒绝后再次申请权限是不会弹框提醒的。用户点击拒绝,并勾选不再提示,下次请求权限时,系统弹窗不会再出现,而且为,此时你的权限申请被用户彻底拒绝,需要跳转到系统设置页手动允许权限。 版权声明:本文已授权微信公众号:Android必修课,转载请申明出处Android6.0以上的系统中,引入了运行时权限检查,运行时权限分为正常权限和危险权限,当我们的...

    hedzr 评论0 收藏0
  • 解读Android官方开发指导 - 运行权限

    摘要:权限申请官方开发指导上使用在中已经申明的危险权限时需要用户授权。下面结合官方的开发指导对这几个做下说明。检查是否已经具有了相关权限。如,和权限就是属于组的。分门别类不仅仅是为了方便容易阅读,组内权限在申请上也是有关联的。 showImg(https://segmentfault.com/img/remote/1460000006962053); 系统权限简介 Android出于系统稳定...

    stackvoid 评论0 收藏0
  • android 权限EasyPermissions

    摘要:文章链接众所周知,在之后,如果应用程序需要危险权限,则用户必须明确向应用授予该权限。今天推荐一个权限相关的库。以相机权限来看,先看下不使用库的情况下的授权方式。用于检查权限是否授权,第二个参数可传多个权限值。 文章链接:https://mp.weixin.qq.com/s/H63Sn03xV0JoINXB4SWWKA 众所周知,在android 6.0之后,如果应用程序需要危险权限,...

    animabear 评论0 收藏0
  • android 权限EasyPermissions

    摘要:文章链接众所周知,在之后,如果应用程序需要危险权限,则用户必须明确向应用授予该权限。今天推荐一个权限相关的库。以相机权限来看,先看下不使用库的情况下的授权方式。用于检查权限是否授权,第二个参数可传多个权限值。 文章链接:https://mp.weixin.qq.com/s/H63Sn03xV0JoINXB4SWWKA 众所周知,在android 6.0之后,如果应用程序需要危险权限,则用户...

    用户84 评论0 收藏0

发表评论

0条评论

whatsns

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<