Android6.0:动态权限申请

不使用第三方的权限库,只用系统API

系统API请求权限的时候只可以单个请求。

整个过程中有2个权限提示dialog
第一个:当我们第一次打开app,需要权限时,会弹出下面的dialog
这里写图片描述

对应的代码是:

ActivityCompat.requestPermissions(Activity, permissions, requestCode)

第二个:第一个的dialog,我么点击了拒绝后,当再次需要该权限时,会弹出下面的dialog
这里写图片描述

对应的代码还是:

ActivityCompat.requestPermissions(Activity, permissions, requestCode)

PackageManager中的常量
int PERMISSION_GRANTED = 0有权限
PERMISSION_DENIED = -1没有权限
先介绍用的的API:
检查是单个权限,这2个表达式结果是int

ActivityCompat.checkSelfPermission(context, permission)
ContextCompat.checkSelfPermission(context, permission)

判断有无权限:

if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
    //没有权限
    ActivityCompat.requestPermissions(this, permissions, 50);

} else {
    //有权限
}

请求权限:

ActivityCompat.requestPermissions(Activity, permissions, requestCode)
ContextCompat.requestPermissions(Activity, permissions, requestCode)

请求权限后,同意或拒绝 后会回调

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

在此方法中判断是否同意请求:

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

    if (requestCode == 50 && permissions[0].equals(permission) && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            show("请求权限成功");
    } else {
        show("请求权限失败,请到设置页面设置权限");
    }
}

是否需要权限解释:

boolean flag=shouldShowRequestPermissionRationale(Activity, permission)

true:用户拒绝此权限
false:用户拒绝此权限+“不再询问”

注意:一定要看上面说的那3中dialog。使用系统API,只有前2种dialog,分清这几种dialog,有助于分清权限的使用过程。

EasyPermissions

这个是google提供的,github 地址:EasyPermissions
上面官方提供的Sample,采用的maven,国内网络受限,我把libary module(easypermission)去掉了,改用添加远程依赖的方式,地址:
Demo:https://git.oschina.net/libraryDemo/EasyPermissions01
Google Android Guild:正常权限和危险权限
Google Android Guild:在运行时请求权限

效果图:

这里写图片描述

整个过程中有3个权限提示dialog
第一个:当我们第一次打开app,需要权限时,会弹出下面的dialog

这里写图片描述

对应的代码是:

EasyPermissions.hasPermissions(context, permissions)

第二个:第一个的dialog,我么点击了拒绝后,当再次需要该权限时,会弹出下面的dialog
这里写图片描述

对应的代码是:

EasyPermissions.requestPermissions(MainActivity.this, "App需要拍照权限", RC_CAMERA_PERM, permissions);

第三个:当我们点击了拒绝+不再询问时,会弹出下面的dialog
这里写图片描述

对应的代码是:

//自定义设置
  new AppSettingsDialog.Builder(this)
          .setTitle("拍照权限")
          .setRationale("缺少拍照权限,将要跳转到设置界面")
          .setPositiveButton("同意")
          .setNegativeButton("取消")//"" 是无法隐藏取消按钮的,必须加空格
          .setRequestCode(requestCode)
          .build()
          .show();

gradle

dependencies {
    ...
    compile 'pub.devrel:easypermissions:0.2.1'
    ...
}

XML中还是需要声明权限-例:

<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

逻辑步骤

逻辑:
执行拍照操作,先判断有没有权限,有:拍照;没有:请求权限。
请求权限后,会弹出dialog,点击“确定”、“取消”会走不同的方法。
“确定”:onPermissionsGranted(int requestCode, List<String> perms)
“取消”:onPermissionsDenied(int requestCode, List<String> perms)

步骤
- 重写方法onRequestPermissionsResult(...)
- 需要权限的时候,先检查有没有这个权限

  • 有:进行逻辑操作
  • 没有:请求权限
  • (可选)让类Activity或Fragment实现EasyPermissions.PermissionCallbacks
  • (可选)系统设置完成后

onRequestPermissionsResult(...)把结果返回给EasyPermissions
onPermissionsGranted(...)``onPermissionsDenied(...)ActivityFragment实现EasyPermissions.PermissionCallbacks接口必须实现的方法。
hasPermissions(...)检查是否有权限,内部调用的是checkSelfPermission(...)
requestPermissions(...)请求权限
somePermissionPermanentlyDenied(this, perms)如果必须需要改权限

Step1:onRequestPermissionsResult(…)

重写此方法,将结果转发给EasyPermissions

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

如果是多个权限

String[] perms = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS };

如果app刚开始安装,没有权限,那么会弹出下图:(有的手机安装时没有让你权限给与提示,只有打开app用到该权限时才提示)
这里写图片描述
如果点击“允许”,当下次再点击Camera按钮是,直接进入业务逻辑。
如果点击“拒绝”,我们再次点击Camera时,弹出下图,文字是我们自己写的

Step2:需要权限的时候,先检查有没有这个权限

注意:
EasyPermissions.hasPermissions(Activity, Manifest.permission.CAMERA)有2步操作
1 方法返回的boolean(是否有权限)
2 如果没有权限,会展示给与权限页面(就是上图)

当点击“允许”后,进入我们自己写的逻辑页面,
当点击“拒绝”后,会进入onPermissionsDenied()方法,前提是Activity/Fragment实现了EasyPermissions.PermissionCallbacks接口

if (EasyPermissions.hasPermissions(MainActivity.this, Manifest.permission.CAMERA)) {
    //有此权限
    toast.setText("已经有CAMERA权限了");
    toast.show();
} else {//没有此权限,需要重新申请  getResources().getString(R.string.positive_button)
    EasyPermissions.requestPermissions(this, "请求camera权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
}

Step3:让类Activity或Fragment实现EasyPermissions.PermissionCallbacks

implements EasyPermissions.PermissionCallbacks

当我们点击了 “拒绝”+“不再询问”后,我们在点击Button,不会弹出任何dialog,如果要弹出提示页面,需要在

if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
    ///
}

方法中自定义请求权限的dialog。
需要重写的方法:

//同意授权
@Override
public void onPermissionsGranted(int requestCode, List<String> list) {
    toast.setText("Granted");
    toast.show();
}

//拒绝授权。 同时点击“不在询问” + 拒绝后,调用这个方法
@Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
    //用户点击拒绝后+不再询问后,弹出dialog,点击“确定”会去设置界面
    if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {

        new AppSettingsDialog.Builder(this, "点击确定去设置界面设置权限")
                .setTitle("Title")
                .setPositiveButton("确定2")
                .setNegativeButton("取消2", null /* click listener */)
                .setRequestCode(requestCode)
                .build()
                .show();
    }
}

上面的Builder(activity,rationale)过时了,下面的是可行的

new AppSettingsDialog.Builder(this)
        .setTitle("拍照权限")
        .setRationale("缺少拍照权限,将要跳转到设置界面")
        .setPositiveButton("同意")
        .setNegativeButton(" ")//"" 是无法隐藏取消按钮的,必须加空格
        .setRequestCode(requestCode)
        .build()
        .show();

Step4;系统设置完成后

在系统设置界面,设置完权限后,返回当前界面后调用这个方法
requestCoderequestPermissions(...)中设置的
resultCode不需要判断,因为不管你给不给权限,resultCode还是RESULT_CANCELED,也就是0,所以需要重新判断有没有权限

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == RC_LOCATION_CONTACTS_PERM) {
        toast.setText("onActivityResult定位和获取联系人权限");
        toast.show();
    } else if (requestCode == RC_CAMERA_PERM) {
        toast.setText("onActivityResult拍照权限");
        toast.show();
        getCamera();
    }
}
@AfterPermissionGranted(RC_CAMERA_PERM)
private void getCamera() {
    String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION};
    if (EasyPermissions.hasPermissions(context, Manifest.permission.CAMERA)) {
        toast.setText("已经有Camera权限了");
        toast.show();
    } else {
        EasyPermissions.requestPermissions(MainActivity.this, "App需要拍照权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
    }
}

问题

如何隐藏“取消”按钮?

是无法隐藏取消按钮的,必须加空格,已空白的效果显示,如果点击取该空白,dialog仍然会消失。

new AppSettingsDialog.Builder(this)
  .setNegativeButton(" ")

这里写图片描述

如果点击了“拒绝”+“不在提示”,那么就真的不会在弹出dialog提示了,如果我们还想要提示,怎么办呢?

需要我们在方法onPermissionsDenied(...)中再创建dialog

if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
    new AppSettingsDialog.Builder(this).build().show();
}

完整代码

public class MainActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks {

    private Toast toast;
    private static final int RC_CAMERA_PERM = 100;//camera权限
    private static final int RC_LOCATION_CONTACTS_PERM = 101;//定位和联系人权限

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toast = Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT);

        findViewById(R.id.btn_camera).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                cameraTask();
            }
        });

        findViewById(R.id.btn_location_contracts).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                locationAndContactsTask();
            }
        });
    }

    @AfterPermissionGranted(RC_LOCATION_CONTACTS_PERM)
    private void locationAndContactsTask() {
        String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_CONTACTS};
        if (EasyPermissions.hasPermissions(MainActivity.this, perms)) {
            toast.setText("已经获取READ_CONTACTS + ACCESS_FINE_LOCATION权限了");
            toast.show();
        } else {
            EasyPermissions.requestPermissions(this, "请求定位和联系人权限", RC_LOCATION_CONTACTS_PERM, perms);
        }
    }

    @AfterPermissionGranted(RC_CAMERA_PERM)
    private void cameraTask() {
        if (EasyPermissions.hasPermissions(MainActivity.this, Manifest.permission.CAMERA)) {
            //有此权限
            toast.setText("已经有CAMERA权限了");
            toast.show();
        } else {//没有此权限,需要重新申请  getResources().getString(R.string.positive_button)
            EasyPermissions.requestPermissions(this, "请求camera权限", RC_CAMERA_PERM, Manifest.permission.CAMERA);
        }
    }

    //官方demo推荐重写这个方法,没发现什么用处
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Forward results to EasyPermissions
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    //同意授权
    @Override
    public void onPermissionsGranted(int requestCode, List<String> list) {
        toast.setText("Granted");
        toast.show();
    }

    //同时点击“不在询问” + 拒绝后,调用这个方法
    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        //用户点击拒绝后,弹出dialog,点击“确定”会去设置界面
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {

            new AppSettingsDialog.Builder(this, "点击确定去设置界面设置权限")
                    .setTitle("Title")
                    .setPositiveButton("确定2")
                    .setNegativeButton("取消2", null /* click listener */)
                    .setRequestCode(requestCode)
                    .build()
                    .show();
        }
    }

    //在系统设置界面,设置完权限后,返回当前界面后调用这个方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == RC_LOCATION_CONTACTS_PERM) {
            toast.setText("onActivityResult定位和获取联系人权限");
            toast.show();
        } else if (requestCode == RC_CAMERA_PERM) {
            toast.setText("onActivityResult拍照权限");
            toast.show();
        }
    }
}

checkSelfPermission(“….”)

系统自带的检查权限的方法(API>=23)

int selfPermission = checkSelfPermission("android.permission.CAMERA");

0:有权限;-1:没有权限。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值