Android 6.0 RuntimePermission

android6.0棉花糖,app将不会在安装的时候授予权限。取而代之的是,app不得不在运行时一个一个询问用户授予权限。

     
     
1
2
3
4
5
6
7
8
9
10
     
     
android {
compileSdkVersion 23
...
defaultConfig {
...
targetSdkVersion 23
...
}
}

如何app/build.gradle是23的话,在6.0上运行一些权限,没有做处理,会直接崩溃:

     
     
1
2
3
4
5
6
     
     
...
Caused by: java.lang.SecurityException: Permission Denial:
opening provider com.android.providers.contacts.ContactsProvider2 from ProcessRecord
{c3b3c66 16712:com.wuxiaolong.apksample/u0a62} (pid=16712, uid=10062)
requires android.permission.READ_CONTACTS or android.permission.WRITE_CONTACTS
...

如果targetSdkVersion 22,就不会发生这样的错误,下面就来实践下这个6.0运行的权限。

效果预览

按照惯例,先上效果图:

说明:第一次请求授权,是没有“不再询问”,拒绝后,再次请求授权,就会出现“不再询问”。

实践

AndroidManifest.xml

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

代码调用

在需要使用到权限之前调用以下代码:

     
     
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
     
     
private void mayRequestContacts() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
switch (checkSelfPermission(Manifest.permission.READ_CONTACTS)) {
case PackageManager.PERMISSION_GRANTED:
// 已有授权
Log.i( "wxl", "已有授权");
break;
case PackageManager.PERMISSION_DENIED:
// 没有权限:尚未请求过权限,
// 或者请求授权被拒绝,
// 或者曾经授权过,但被用户在设置中禁用权限
Log.i( "wxl", "没有权限:尚未请求过权限,或者请求授权被拒绝," +
"或者曾经授权过, 但被用户在设置中禁用权限");
/**
* 如果用户勾上了“不再询问”,这时候就不应弹请求权限的对话框,
* 可以在请求权限之前用
* shouldShowRequestPermissionRationale判断用户是否拒绝过,
* 如果返回true,表示用户拒绝过。
*/
Log.i( "wxl", "shouldShowRequestPermissionRationale=="
+ shouldShowRequestPermissionRationale(READ_CONTACTS));
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(mEmailView,
R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions( new String[]{READ_CONTACTS},
REQUEST_READ_CONTACTS);
}
}).show();
} else {
requestPermissions( new String[]{READ_CONTACTS},
REQUEST_READ_CONTACTS);
}
break;
default:
break;
}
}
}

checkSelfPermission:检查权限
requestPermissions:请求权限
shouldShowRequestPermissionRationale:判断用户是否拒绝过

授权回调

不管是允许或拒绝,都会回调:

     
     
1
2
3
4
5
6
7
8
9
10
11
12
13
     
     
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,@NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 &&
grantResults[ 0] == PackageManager.PERMISSION_GRANTED) {
// 授权请求被通过,读取通讯录
Log.i( "wxl", "授权请求被通过,读取通讯录");
} else {
Log.i( "wxl", "授权请求不被通过");
}
}
}

多个权限

     
     
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
     
     
@TargetApi(Build.VERSION_CODES.M)
private void checkPermissions() {
List<String> permissionsNeeded = new ArrayList<>();
final List<String> permissionsList = new ArrayList<>();
if (deniedPermission(permissionsList, Manifest.permission.ACCESS_FINE_LOCATION))
permissionsNeeded.add( "GPS");
if (deniedPermission(permissionsList, Manifest.permission.READ_CONTACTS))
permissionsNeeded.add( "Read Contacts");
if (permissionsList.size() > 0) {
if (permissionsNeeded.size() > 0) {
// Need Rationale
String message = "You need to grant access to " + permissionsNeeded.get( 0);
for ( int i = 1; i < permissionsNeeded.size(); i++)
message = message + ", " + permissionsNeeded.get(i);
requestPermissions(permissionsList.toArray( new String[permissionsList.size()]), REQUEST_PERMISSIONS);
}
}
}
@TargetApi(Build.VERSION_CODES.M)
private boolean deniedPermission(List<String> permissionsList, String permission) {
if (checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
permissionsList.add(permission);
// true,表示用户拒绝过
if (shouldShowRequestPermissionRationale(permission)) {
return true;
}
}
return false;
}
/**
* Callback received when a permissions request has been completed.
*/
@Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_PERMISSIONS) {
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_CONTACTS, PackageManager.PERMISSION_GRANTED);
// Fill with results
for ( int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for ACCESS_FINE_LOCATION
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
Log.i( "wxl", "授权请求被通过");
} else {
// Permission Denied
Log.i( "wxl", "授权请求不被通过");
}
}
}

权限分组

权限那么多,如果一个个判断,岂不是会疯掉,如图:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值