简书链接:【原创】Android申请权限的套路代码存档教你判断第一次拒绝第二次拒绝和永久拒绝
文章字数:1203,阅读全文大约需要4分钟
具体参考https://www.jianshu.com/p/88e0a371161c

模板代码

1
2
3
4
5
6
7
8
9
10
11
12
13
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission("android.permission.READ_EXTERNAL_STORAGE") == PackageManager.PERMISSION_GRANTED) {
return false;
}
if (shouldShowRequestPermissionRationale("android.permission.READ_EXTERNAL_STORAGE")) {
Toast.makeText(this, "请一定要给与权限!再给你一次选择的机会", Toast.LENGTH_SHORT).show();
requestPermissions(new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 2);
} else {
requestPermissions(new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 2);//首次申请
}
return true;
}
return true;

###循环单个申请、以此弹出申请对话框。
这个逻辑推荐在进入app的时候弄,我发现很多app懒得麻烦,一次性申请完。

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 private void initRequestPermissionListAndStartRequest() {
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_PHONE_STATE);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.CAMERA)) {
waitRequestPermissionGroup.add(Manifest.permission.CAMERA);
}
if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.CALL_PHONE)) {
waitRequestPermissionGroup.add(Manifest.permission.CALL_PHONE);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
waitRequestPermissionGroup.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_SMS);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_NETWORK_STATE);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
waitRequestPermissionGroup.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.MODIFY_AUDIO_SETTINGS)) {
waitRequestPermissionGroup.add(Manifest.permission.MODIFY_AUDIO_SETTINGS);
}


if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.INSTALL_SHORTCUT)) {
waitRequestPermissionGroup.add(Manifest.permission.INSTALL_SHORTCUT);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.UNINSTALL_SHORTCUT)) {
waitRequestPermissionGroup.add(Manifest.permission.UNINSTALL_SHORTCUT);
}


if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.SEND_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.SEND_SMS);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS)) {
waitRequestPermissionGroup.add(Manifest.permission.RECEIVE_SMS);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_FINE_LOCATION);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WAKE_LOCK)) {
waitRequestPermissionGroup.add(Manifest.permission.WAKE_LOCK);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.WRITE_CALL_LOG)) {
waitRequestPermissionGroup.add(Manifest.permission.WRITE_CALL_LOG);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.KILL_BACKGROUND_PROCESSES)) {
waitRequestPermissionGroup.add(Manifest.permission.KILL_BACKGROUND_PROCESSES);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.GET_TASKS)) {
waitRequestPermissionGroup.add(Manifest.permission.GET_TASKS);
}

if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.VIBRATE)) {
waitRequestPermissionGroup.add(Manifest.permission.VIBRATE);
}


if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE)) {
waitRequestPermissionGroup.add(Manifest.permission.ACCESS_WIFI_STATE);
}

/* if (!PermissionsUtils.checkSelfPermission(this, Manifest.permission.BLUETOOTH)) {
waitRequestPermissionGroup.add(Manifest.permission.BLUETOOTH);
}

*/
if (waitRequestPermissionGroup.size() > 0) {

PermissionsUtils.requestPermission(this, waitRequestPermissionGroup.get(0), REQUEST_LOOP);
}

}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] gradResults) {

if (requestCode == REQUEST_LOOP) {
Log.w(TAG, "获取" + permissions[0] + "结果是成功:" + (gradResults.length > 0 && gradResults[0] == PackageManager.PERMISSION_GRANTED) + ",列表中共有" + waitRequestPermissionGroup.size() + "个权限等待申请!");
if (waitRequestPermissionGroup.size() > 0) {
waitRequestPermissionGroup.remove(0);

}

if (waitRequestPermissionGroup.size() > 0) {

String premissionStr = waitRequestPermissionGroup.get(0);
Log.w(TAG, "开始申请" + premissionStr + "权限!");
if (PermissionsUtils.requestPermission(this, premissionStr, requestCode)) {
onRequestPermissionsResult(REQUEST_LOOP, new String[]{premissionStr}, new int[]{});
}
} else {
if (gradResults.length > 0 && gradResults[0] != PackageManager.PERMISSION_GRANTED) {
AppContext.showToast(permissions[0] + "权限请求失败");
}else{
Log.w(TAG, "所有权限申请完毕!");
}
}

}

}

写的不太对,这是比亚迪的测试结果,比较有争议的就是shouldShowRequestPermissionRationale实际上我测试的结果如果是第一次或者被永久拒绝就返回false, 如果没有被拒绝,再次打开app申请就返回true,返回true一定可以申请弹出,返回false,则不一定,目前没有判断永久拒绝的方法。

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
33
34
35
36
37
38
39
40
41
42
/MY_PERMISSION   Manifest.permission.BYDAUTO_AC_COMMON
public static void verify(Activity context) {
// DeviceBaseInfoUtils.getBydVin(Activity activity)
if (context.checkSelfPermission(MY_PERMISSION)//判断是否拥有这个方法,如果 拥有则不等于 PERMISSION_GRANTED
!= PERMISSION_GRANTED) {
Log.w(TAG, "checkSelfPermission ==FALSE 上次是拒绝了此权限的");
//如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。

if (context.shouldShowRequestPermissionRationale(MY_PERMISSION)) {//如果非第一次 拒绝但是还没有设置永久拒绝会走这个逻辑, 这个时候还是可以申请权限的。
Log.w(TAG, "shouldShowRequestPermissionRationale true");
Toast.makeText(context, "为了您的安全,请一定要同意权限申请!", Toast.LENGTH_SHORT).show();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN);
} else {
Log.w(TAG, "shouldShowRequestPermissionRationale false 第一次或者被永久拒绝"); //第一次 或者被永久拒绝走这个逻辑,
Log.w(TAG, "requestPermissions");
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN);//如果永久拒绝,
}
} else {
// 拥有权限
Log.w(TAG, "checkSelfPermission ==true");
checkLogic(context);
}


}

public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
if (REQUEST_CODE_VIN == requestCode) {
Log.w(TAG, "onRequestPermissionsResult permissions:" + Arrays.toString(permissions) + ",grantResults:" + Arrays.toString(grantResults));
if (permissions != null && permissions.length > 0 && permissions[0].equals(MY_PERMISSION)) {

if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Log.w(TAG, "onRequestPermissionsResult 获取成功");
checkLogic(activity);
} else {
Log.w(TAG, "onRequestPermissionsResult 获取失败!");
doFailLogic();
}
}
}
}

那么永久拒绝的判断

根据执行时间就可以推测了。

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
 //MY_PERMISSION   Manifest.permission.BYDAUTO_AC_COMMON
public static void verify(Activity context) {
// DeviceBaseInfoUtils.getBydVin(Activity activity)
if (context.checkSelfPermission(MY_PERMISSION)//判断是否拥有这个方法,如果 拥有则不等于 PERMISSION_GRANTED
!= PERMISSION_GRANTED) {
Log.w(TAG, "checkSelfPermission ==FALSE 上次是拒绝了此权限的");
//如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true。

if (context.shouldShowRequestPermissionRationale(MY_PERMISSION)) {
Log.w(TAG, "shouldShowRequestPermissionRationale true");
Toast.makeText(context, "为了您的安全,请一定要同意权限申请!", Toast.LENGTH_SHORT).show();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN_SECOND);
//如果非第一次 拒绝但是还没有设置永久拒绝会走这个逻辑, 这个时候还是可以申请权限的。
} else {
Log.w(TAG, "shouldShowRequestPermissionRationale false 第一次或者被永久拒绝"); //第一次 或者被永久拒绝走这个逻辑,
Log.w(TAG, "requestPermissions");
sRequestTime = new Date().getTime();
context.requestPermissions(new String[]{MY_PERMISSION}, REQUEST_CODE_VIN_FIRST_OR_LAST);//如果永久拒绝,
}
} else {
// 拥有权限
Log.w(TAG, "checkSelfPermission ==true");
checkLogic(context);
}


}

public static void onRequestPermissionsResult(Activity activity, int requestCode, String[] permissions, int[] grantResults) {
if (REQUEST_CODE_VIN_SECOND == requestCode || requestCode == REQUEST_CODE_VIN_FIRST_OR_LAST) {
Log.w(TAG, "onRequestPermissionsResult permissions:" + Arrays.toString(permissions) + ",grantResults:" + Arrays.toString(grantResults));
if (permissions != null && permissions.length > 0 && permissions[0].equals(MY_PERMISSION)) {

if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Log.w(TAG, "onRequestPermissionsResult 获取成功");

checkLogic(activity);
} else {
long distance = new Date().getTime() - sRequestTime;
if (BuildConfig.DEBUG) {
Log.w(TAG, "执行回调间隔:" + distance);
}
if (distance < 800 && requestCode == REQUEST_CODE_VIN_FIRST_OR_LAST) {
Log.w(TAG, "onRequestPermissionsResult 获取失败 推测是永久拒绝!");

} else {
Log.w(TAG, "onRequestPermissionsResult 获取失败!");

}
doFailLogic();//拒绝了
}
}
}
}

至于为什么是原创,因为我发现网上似乎没有这样的方法,而且很多文章讲的乱七八糟,甚至比亚迪的sdk demo都写错了,认为第二次就应该卸载才行。。

第一 shouldShowRequestPermissionRationale为true,表示已经申请过了,但是没有永久拒绝,,永久拒绝和第一次都会返回false,

第二个requestPermissions只能调用一次,也就是说权限对话框弹出来的时候,如果方法继续执行又执行了requestPermissions那么会马上收到权限失败的回调,而且 回调中的权限数组和结果int数组 长度是0的.
偏门:在做自动化插入任何app的时候这种问题是无法避免的,无法智能

第三个/如果requestPermissions传递了多个参数,那么回一次请求权限弹出对话框,知道所有权限的一个接一个的弹出之后,才会进行回调,这个时候可能包含多个成功结果失败与否的数组。
第四个/如果弹出的时候finish或者请求之后马上finish,前者虽然能看到,但是finish了看不到任何回调,后者则看不到弹出权限对话框,也不会回调结果
偏门:这个做自动化才会感受到这些问题