Android6.0动态权限适配&XMPermissions

个人博客地址 http://dandanlove.com/

Android6.0动态权限适配&XMPermissions

permission.jpg

Android6.0动态权限

简介

从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。此方法可以简化应用安装过程,因为用户在安装或更新应用时不需要授予权限。它还让用户可以对应用的功能进行更多控制;例如,用户可以选择为相机应用提供相机访问权限,而不提供设备位置的访问权限。用户可以随时进入应用的“Settings”屏幕调用权限。摘自Android官网:在运行时请求权限

targetSdkVerion

我们在开发的时候需要指定minSdkVersiontargetSdkVerion

  • minSdkVersion为app最低适配的版本,低于该版本的手机无法安装;
  • targetSdkVerion简单来说就代表着你的App能够适配的系统版本,意味着你的App在这个版本的手机上做了充分的 前向 兼容性处理和实际测试。其实我们写代码时都是经常干这么一件事,就是 if(Build.VERSION.SDK_INT >= 23) { … } ,这就是兼容性处理最典型的一个例子。如果你的target设置得越高,其实调用系统提供的API时,所得到的处理也是不一样的,甚至有些新的API是只有新的系统才有的;

Android6.0特殊权限Special Permissions

看权限名就知道特殊权限比危险权限更危险,特殊权限需要在manifest中申请并且通过发送Intent让用户在设置界面进行勾。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//SYSTEM_ALERT_WINDOW
private static final int REQUEST_CODE = 1;
private void requestAlertWindowPermission(){
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:"+ getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}
@Override
protected void onActivityResult(intrequestCode, intresultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE) {
if(Settings.canDrawOverlays(this)) {
Log.i(LOGTAG, "onActivityResult granted");
}
}
}
//WRITE_SETTINGS 修改系统设置
private static final int REQUEST_CODE_WRITE_SETTINGS = 2;
private void requestWriteSettings(){
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:"+ getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
}
@Override
protected void onActivityResult(intrequestCode, intresultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == REQUEST_CODE_WRITE_SETTINGS) {
if(Settings.System.canWrite(this)) {
Log.i(LOGTAG, "onActivityResult write settings granted");
}
}
}

Android6.0普通权限normal permission

普通权限不会对用户的隐私和安全产生太大的风险,所以只需要在AndroidManifest.xml中声明即可.

Android6.0危险权限dangerous permission

  • Normal Permission:写在xml文件里,那么App安装时就会默认获得这些权限,即使是在Android6.0系统的手机上,用户也无法在安装后动态取消这些normal权限,这和以前的权限系统是一样的,不变。
  • Dangerous Permission:还是得写在xml文件里,但是App安装时具体如果执行授权分以下几种情况:
    • 1、targetSDKVersion < 23 & API(手机系统) < 6.0 :安装时默认获得权限,且用户无法在安装App之后取消权限。
    • 3、targetSDKVersion < 23 & API(手机系统) >= 6.0 :安装时默认获得权限,但是用户可以在安装App完成后动态取消授权( 取消时手机会弹出提醒,告诉用户这个是为旧版手机打造的应用,让用户谨慎操作 )。
    • 2、targetSDKVersion >= 23 & API(手机系统) < 6.0 :安装时默认获得权限,且用户无法在安装App之后取消权限。
    • 4、targetSDKVersion >= 23 & API(手机系统) >= 6.0 :安装时不会获得权限,可以在运行时向用户申请权限。用户授权以后仍然可以在设置界面中取消授权,用户主动在设置界面取消后,在app运行过程中可能会出现crash。

Dangerous permissions and permission groups(危险权限和权限组)

同一组的任何一个权限被授权了,其他权限也自动被授权。例如,一旦WRITE_CONTENTS被授权了,APP也有READ_CONTACTS和GET_ACCOUNTS了。

permission-group dangerous permissions
CALENDAR(日历) READ_CALENDAR , WRITE_CALENDAR
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(使用SIP协议 , PROCESS_OUTGOING_CALLS(程序拨出电话)
SENSORS(传感器) BODY_SENSORS
SMS SEND_SMS , RECEIVE_SMS , READ_SMS , RECEIVE_WAP_PUSH , RECEIVE_MMS
TORAGE(存储) READ_EXTERNAL_STORAGE ,WRITE_EXTERNAL_STORAGE

如何开始动态申请权限

判断权限是否具有某项权限

1
2
3
ContextCompat.checkSelfPermission(Context context,String permission);
ActivityCompat.checkSelfPermission(Context context, String permission);
activity.checkSelfPermission(String permission);

申请权限

1
2
3
4
ActivityCompat.requestPermissions(Activity activity,String[] permissions,int requestCode);
activity.requestPermissions(String[] permissions, int requestCode);
//申请权限回调方法,在Activity或Fragment重写
onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

是否要提示用户申请该权限的缘由,sdk小于23恒为false

1
2
3
4
5
6
7
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission)
0、之前没有拒绝过此权限的申请(第一次安装后请求权限前调用):false
1、曾经被拒绝过权限后再调用:true
2、曾经被拒绝过权限且不再询问后再调用:false
3、系统不允许任何程序获取该权限:false
4、查看源码得知安卓6.0以下返回:false
5、总是允许权限后再次调用:false

在APP使用过程中,从设置中更改权限

如果应用程序的某个业务逻辑需要使用权限,但用户没有选择开启。那么最好引导用户去设置界面修改应用程序的权限。

XMPermissions

导读

如果我们应用需要动态申请危险权限,按照Google官方问档我们需要在activity或者fragment中的onRequestPermissionsResult方法进行回调处理。一个执行任务代码需要分开写在两处地方,这我们的代码会变得很不优雅。

有没有链式、流式或者注解的方式去解决这个问题?有而且很多,以下是我在github 上找的start 最多的开源库。

RxPermissions RxJava流式用法;
XXPermissions 链式用法;
permissions4m 注解用法;

个人对注解使用不太感冒,而且项目有用到Rxjava的地方。
综上所述,我在RxPermissionsXXPermissions 基础上开发了 XMPermissions

依赖

1
implementation 'com.tzx.lib:xmpermission:1.0.0'

使用

1
2
3
4
5
6
7
8
9
10
11
12
public interface OnPermission {
/**
* 本次申请的权限全部通过
*/
void hasPermission();

/**
* 本次申请的权限没有全部通过
* @param granteds
*/
void noPermission(List<PermissionState> granteds);
}

RxJava

1
2
3
4
5
6
7
8
9
10
XMPermissions.with(this)
.request(Permission.Group.STORAGE, Permission.Group.PHONE)
.subscribe(new SimpleSubscriber<List<PermissionState>>() {
@Override
public void onNext(List<PermissionState> permissionStates) {
for (PermissionState s: permissionStates) {
Log.d("tanzhenxing:", s.toString());
}
}
});

链式调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
XMPermissions.with(this)
//.constantRequest() //可设置被拒绝后继续申请,直到用户授权或者永久拒绝
.permission(Permission.Group.STORAGE, Permission.Group.CALENDAR)
.request(new OnPermission() {

@Override
public void hasPermission() {
Toast.makeText(MainActivity.this, "获取权限成功", Toast.LENGTH_SHORT).show();
}

@Override
public void noPermission(List<PermissionState> granteds) {
for (PermissionState s: granteds) {
Log.d("tzx:", s.toString());
}
}

});

跳转到应用权限设置页面

1
XMPermissions.gotoPermissionSettings(content);

6.0动态权限适配总结

有了XMPermissions 适配6.0动态权限就非常简单了。将targetVersion升级到23,然后每个使用储存、定位、电话、相机、录音等危险权限的地方做权限的check

当然这么做非常麻烦像储存、定位、电话这三个权限我们几乎每次接口访问都需要获取,所以我们可以将一些权限申请在应用启动前置。

  • 转转:储存、定位、电话前置
  • 58同城: 存储、电话前置
  • 京东: 定位、电话前置
  • 手机淘宝: 电话前置
  • 手机百度: 存储前置

在进行短信发送和打电话时,不需要权限也可以哦~!我自己测试了4个主流厂商的8款手机。

随着Android系统的不断更新,后续后问题会继续同步哒~!

文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦~!~!

想阅读作者的更多文章,可以查看我 个人博客 和公共号:

振兴书城
文章目录
  1. 1. 个人博客地址 http://dandanlove.com/
  2. 2. Android6.0动态权限适配&XMPermissions
  3. 3. Android6.0动态权限
    1. 3.1. 简介
    2. 3.2. targetSdkVerion
    3. 3.3. Android6.0特殊权限Special Permissions
    4. 3.4. Android6.0普通权限normal permission
    5. 3.5. Android6.0危险权限dangerous permission
    6. 3.6. Dangerous permissions and permission groups(危险权限和权限组)
    7. 3.7. 如何开始动态申请权限
      1. 3.7.1. 判断权限是否具有某项权限
      2. 3.7.2. 申请权限
      3. 3.7.3. 是否要提示用户申请该权限的缘由,sdk小于23恒为false
    8. 3.8. 在APP使用过程中,从设置中更改权限
  4. 4. XMPermissions
    1. 4.1. 导读
    2. 4.2. 依赖
    3. 4.3. 使用
      1. 4.3.1. RxJava
      2. 4.3.2. 链式调用
      3. 4.3.3. 跳转到应用权限设置页面
  5. 5. 6.0动态权限适配总结
,