android运行时权限封装,GitHub - leavesC/PermissionSteward: 对Android 6.0运行时权限操作的封装...

本文介绍了如何使用PermissionSteward库简化Android6.0运行时权限的处理,包括单个和多个权限的申请,以及在用户拒绝权限后的处理策略,如自定义权限说明对话框和引导用户到设置界面主动授权。同时提供了通过接口和注解两种方式实现回调的示例代码。
摘要由CSDN通过智能技术生成

如今网络上对于 Android 6.0 运行时权限进行分析的文章已经很多了,不了解的可以看我的另一篇文章: Android 6.0 运行时权限解析

Android 6.0 运行时权限对于用户来说还是挺好的,对于开发者来说就多了很多工作了,如果不进行一些封装操作的话,会多出很多无谓的代码量,这里来提供一个对 Android 6.0 运行时权限的封装库,以简化操作:PermissionSteward

先看下效果图:

在第一次申请权限被拒绝后,在第二次申请时显示一个对话框向用户说明应用为什么需要这个权限

301ee28bfb6fb07cbeaab405e82b7e80.gif

可以自定义权限申请说明文本

0aab73a8d928f31726b0499ee064198a.gif

一次性申请多个权限,在用户拒绝权限且选了不再提醒时,引导用户跳转到设置界面主动开启权限

82345af16c26e934a8441717b0511a82.gif

这里要说明一下,我的这个封装库是基于GitHub上这位的源码来修改的:AndPermission

这两天看到了这个开源库,就研究了一下源码,感觉有挺多地方需要向作者学习的,不过有些地方感觉也不是太好,代码也没有注释,就修改了一下代码,并加上了详细注释

PermissionSteward 支持 Activity、android.support.v4.app.Fragment、android.app.Fragment,且权限申请操作都保持一致,回调方式提供注解和接口两种方式

一、通过接口来实现回调

public class ActivityPermissionListenerActivity extends AppCompatActivity implements View.OnClickListener, PermissionListener {

//申请单个权限(日历权限)

private static final int REQUEST_CODE_PERMISSION_CALENDAR = 100;

//申请多个权限(短息和联系人权限)

private static final int REQUEST_CODE_PERMISSION_SMS_AND_CONTACTS = 200;

private static final int REQUEST_CODE_SETTING = 300;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_activity_permission_listener);

findViewById(R.id.btn_request_single).setOnClickListener(this);

findViewById(R.id.btn_request_multi).setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

//一次申请单个权限

case R.id.btn_request_single: {

PermissionSteward.requestPermission(this, REQUEST_CODE_PERMISSION_CALENDAR, Manifest.permission.READ_CALENDAR);

break;

}

//一次申请多个权限

case R.id.btn_request_multi: {

PermissionSteward.requestPermission(this, REQUEST_CODE_PERMISSION_SMS_AND_CONTACTS, Manifest.permission.READ_SMS, Manifest.permission.READ_CONTACTS);

break;

}

}

}

@Override

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

PermissionSteward.onRequestPermissionsResult(requestCode, permissions, grantResults, this);

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

switch (requestCode) {

case REQUEST_CODE_SETTING: {

Toast.makeText(this, "用户从设置界面回来了", Toast.LENGTH_SHORT).show();

break;

}

}

}

@Override

public void onSucceed(int requestCode, List grantPermissionList) {

switch (requestCode) {

case REQUEST_CODE_PERMISSION_CALENDAR: {

Toast.makeText(this, "获取到日历权限", Toast.LENGTH_SHORT).show();

break;

}

case REQUEST_CODE_PERMISSION_SMS_AND_CONTACTS: {

Toast.makeText(this, "获取到短信、联系人权限", Toast.LENGTH_SHORT).show();

break;

}

}

}

@Override

public void onFailed(int requestCode, List deniedPermissionList) {

switch (requestCode) {

case REQUEST_CODE_PERMISSION_CALENDAR: {

Toast.makeText(this, "获取日历权限失败", Toast.LENGTH_SHORT).show();

break;

}

case REQUEST_CODE_PERMISSION_SMS_AND_CONTACTS: {

if (deniedPermissionList.size() == 2) {

Toast.makeText(this, "获取短信、联系人权限失败", Toast.LENGTH_SHORT).show();

} else {

if (deniedPermissionList.get(0).equals(Manifest.permission.READ_SMS)) {

Toast.makeText(this, "获取联系人权限成功、获取短信权限失败", Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(this, "获取短信权限成功、获取联系人权限失败", Toast.LENGTH_SHORT).show();

}

}

break;

}

}

// 如果用户对权限申请操作设置了不再提醒,则提示用户到应用设置界面主动授权

if (PermissionSteward.hasAlwaysDeniedPermission(this, deniedPermissionList)) {

//默认提示语

//PermissionSteward.defaultSettingDialog(this, REQUEST_CODE_SETTING).show();

//自定义提示语

PermissionSteward.defaultSettingDialog(this, REQUEST_CODE_SETTING)

.setTitle("权限申请失败")

.setMessage("需要的一些权限被拒绝授权,请到设置页面手动授权,否则功能无法正常使用")

.setPositiveButton("好,去设置")

.show();

}

}

}

首先让 Activity 实现 PermissionListener 接口

权限申请只需要一句即可

PermissionSteward.requestPermission(this, REQUEST_CODE_PERMISSION_CALENDAR, Manifest.permission.READ_CALENDAR);

REQUEST_CODE_PERMISSION_CALENDAR 是自定义的请求码,用来标识要请求的权限

当权限被拒绝且用户没有选择不再提醒时,当再次申请权限时,以上方法会显示一个默认的用于权限说明的对话框

也可以来自定义权限申请说明

RationaleListener rationaleListener = new RationaleListener() {

@Override

public void showRequestPermissionRationale(int requestCode, Rationale rationale) {

PermissionSteward.rationaleDialog(ActivityPermissionListenerActivity.this, rationale)

.setTitle("权限好像之前被拒绝了")

.setMessage("请授予权限,否则我没法和你玩耍啊~~")

.show();

}

};

PermissionSteward.requestPermission(this, rationaleListener, REQUEST_CODE_PERMISSION_CALENDAR, Manifest.permission.READ_CALENDAR);

然后重写 onRequestPermissionsResult() 方法

@Override

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

PermissionSteward.onRequestPermissionsResult(requestCode, permissions, grantResults, this);

}

当权限申请通过或者被否决时,就会回调 onSucceed() 或者 onFailed() 方法,在这两个方法中进行相应的业务逻辑处理即可

二、通过注解来实现回调

一共有两个注解类

/**

* 用于标注未通过权限申请

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface PermissionFailed {

int value() default -1;

}

/**

* 用于标注通过权限申请

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface PermissionSucceed {

int value() default -1;

}

在代码中为当权限通过或被否决时要调用的方法加上注解,注解值即当申请权限时的请求码

public class ActivityPermissionAnnotationActivity extends AppCompatActivity implements View.OnClickListener {

//申请位置权限

private static final int REQUEST_CODE_PERMISSION_LOCATION = 100;

private static final int REQUEST_CODE_SETTING = 300;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_activity_permission_annotation);

findViewById(R.id.btn_request_single).setOnClickListener(this);

}

@Override

public void onClick(View v) {

if (v.getId() == R.id.btn_request_single) {

//当权限被拒绝且没有选择不再提醒时,当再次申请权限时,以下方法会显示一个默认的用于权限说明的对话框

//PermissionSteward.requestPermission(this, REQUEST_CODE_PERMISSION_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);

//也可以来自定义权限申请说明

RationaleListener rationaleListener = new RationaleListener() {

@Override

public void showRequestPermissionRationale(int requestCode, Rationale rationale) {

PermissionSteward.rationaleDialog(ActivityPermissionAnnotationActivity.this, rationale)

.setTitle("权限好像之前被拒绝了")

.setMessage("请授予权限,否则我没法和你玩耍啊~~")

.show();

}

};

PermissionSteward.requestPermission(this, rationaleListener, REQUEST_CODE_PERMISSION_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);

}

}

@Override

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

PermissionSteward.onRequestPermissionsResult(this, requestCode, permissions, grantResults);

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

switch (requestCode) {

case REQUEST_CODE_SETTING: {

Toast.makeText(this, "用户从设置界面回来了", Toast.LENGTH_LONG).show();

break;

}

}

}

@PermissionSucceed(REQUEST_CODE_PERMISSION_LOCATION)

private void getLocationSucceed(List grantedPermissions) {

Toast.makeText(this, "获取位置权限成功", Toast.LENGTH_SHORT).show();

}

@PermissionFailed(REQUEST_CODE_PERMISSION_LOCATION)

private void getLocationFailed(List deniedPermissionList) {

Toast.makeText(this, "获取位置权限失败", Toast.LENGTH_SHORT).show();

if (PermissionSteward.hasAlwaysDeniedPermission(this, deniedPermissionList)) {

PermissionSteward.defaultSettingDialog(this, REQUEST_CODE_SETTING).show();

}

}

}

同样是用以下方法来申请权限

PermissionSteward.requestPermission(this, REQUEST_CODE_PERMISSION_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION);

重写onRequestPermissionsResult()方法

@Override

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

PermissionSteward.onRequestPermissionsResult(this, requestCode, permissions, grantResults);

}

然后为需要的方法加上注解即可

@PermissionSucceed(REQUEST_CODE_PERMISSION_LOCATION)

private void getLocationSucceed(List grantedPermissions) {

Toast.makeText(this, "获取位置权限成功", Toast.LENGTH_SHORT).show();

}

@PermissionFailed(REQUEST_CODE_PERMISSION_LOCATION)

private void getLocationFailed(List deniedPermissionList) {

Toast.makeText(this, "获取位置权限失败", Toast.LENGTH_SHORT).show();

if (PermissionSteward.hasAlwaysDeniedPermission(this, deniedPermissionList)) {

PermissionSteward.defaultSettingDialog(this, REQUEST_CODE_SETTING).show();

}

}

推荐通过接口的方式来实现回调,注解的方式是通过反射来完成回调的,反射毕竟会消耗一定性能

源代码不算多复杂,有兴趣的可以去研究下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值