您的位置:首页 > 移动开发 > Android开发

Android M新的运行时权限开发者需要知道的一切

2016-07-28 16:22 519 查看
如果permissions没有影响到用户的隐私,系统就会自动授权。如果权限可能会访问到敏感的用户信息,系统则会要求用户处理这种权限要求。

系统permissions被分为两类,normal和dangerous:

Normal permissions不会直接触及到用户的隐私,如果你的app已经在Manifest文件中列出了常规权限,系统则会自动授权。

dangerous的权限能够给app访问用户可信任的数据,如果你的app在Manifest中列出了常规权限,系统则会自动许可。如果你列出了危险权限,那么用户就必须明确地给你的app授权。

然而有效的声明是不同的,这需要依赖于系统的版本以及你的app的target SDK级别:

如果手机运行在android 5.1或者更低,或者你的app的target SDK是22或更低的情况:如果你把dangerous permission列在了Manifest中,则用户必须在安装的时候就要授权;如果他们没有授权权限,则系统就不能安装该应用。

如果手机运行在android 6.0或者更高,并且你的app的SDK是23或者更高的情况:app必须在Manifest列出这些permissions,并且它会在app运行的时候询问每一个它需要的dangerous permission。用户可以授权或者拒绝每一个权限,并且app能够在受限的情况下继续运行,即使用户拒绝了一个permission的请求。

Note:从android 6.0(API level23),用户能够在任何app任何时候取消permissions,即使apptargets 在一个更低的API level下。

检查权限

检查是否有permission,调用ContextCompat.checkSelfPermission()方法。例如下面一段代码展示了怎样检查当activity有permission写日历的权限:

// Assume thisActivity is the current activity

int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,

Manifest.permission.WRITE_CALENDAR);

如果app拥有了该permission,则方法返回PackageManager.PERMISSION_GRANTED,app 能继续这种操作。如果app没有该permission,则方法返回PERMISSION_DENIED,并且app必须明确向用户要求给permission。

请求权限

如果你的app需要一个dangerous permission,并且已经被列在了Manifest中,那么它必须要求用户去给该permission授权。Android提供了若干个方法,你能够使用它们去请求permission。调用这些方法会弹出一个你不能够自定义的标准android dialog。

向用户解释为什么app需要permissions

在某些情况下,你也许想帮助用户理解为什么app需要permission。在你请求一个permission之前,你需要考虑给用户一个合理的解释。请记住,你不会希望用户被说明淹没的,如果你提供了太多的解释,用户或许会发现app令人沮丧,甚至删掉它。

当用户已经拒绝了一个permission请求的时候,你可以使用的一个方法是提供一个解释。如果用户一直试图使用的功能需要一个permission的许可,但是又一直拒绝许可该permission的要求,这或许表明该用户不理解为什么app需要提供该功能。在这种情况下,给用户一个解释或许是个好的方法。

为了找到哪些用户可能需要的解释的情况,android提供了一个使用的方法,shouldShowRequestPermissionRationale().该方法返回true,如果应用程序要求这个许可之前,用户拒绝请求。

Note:如果用户在以前拒绝了permission的请求,并且在permission请求的系统对话框中选择了Don’t ask again的选项,这个方法返回false。如果手机政策禁止应用程序拥有该权限也会返回false。

请求你需要的permission

如果app已经没有它需要的permission,那么app必须调用一个requestPermissions()方法去请求适当的permission。App传递它想要的permissions,以及一个你指定识别此permission整数的request code 。这个方法有同步功能:它立即返回,并在用户响应了对话框后,系统会调用app与结果的的回调方法,通过该app传递给requestPermissions()相同request code。

下面的代码检查app是否有读取用户联系人的permission,并在必要时请求允许:

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {

// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}


处理permissions请求的响应

当你的app请求权限,系统就会向用户显示一个对话框。当用户相应了对对话框,系统就会调用app的onRequestPermissionsResult()方法,传递用户的响应。你的app必须重写该方法,并确定权限是否允许,回调被传递的request和requestPermissions()传递的request code是相同的。例如,如果app请求READ_CONTACTS访问 ,则需要如下的回调方法:

0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// contacts-related task you need to do.

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}

// other 'case' lines to check for other
// permissions this app might request
}
}" data-snippet-id="ext.2b67e9a7c17a78d31f2185e257422b42" data-snippet-saved="false" data-codota-status="done">[code]@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the
// contacts-related task you need to do.

} else {

// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}

// other 'case' lines to check for other
// permissions this app might request
}
}


该系统显示的对话框中描述的app需要访问权限组;它没有列出具体的权限。例如,如果你要求READ_CONTACTS权限,系统对话框,只是说你的应用程序需要访问该设备的联系人。用户只需要为每个权限组授予权限一次。如果app请求组(即在app清单中列出)中任何其他权限,系统自动授权他们。当你请求该权限,系统调用你的onRequestPermissionsResult()回调方法,并传递PERMISSION_GRANTED,它会在用户已明确授予通过系统对话框,你的要求是一样的。

Note:此外,权限的组成组可能会在将来的Android版本中改变。你的代码不应该依赖于假设特定的权限,或不在同一组。

例如,假设你列出的应用程序清单既有READ_CONTACTS也有WRITE_CONTACTS。如果你请求READ_CONTACTS和用户授予权限,然后你要求WRITE_CONTACTS,系统自动授予你该权限,而不必再与用户交互了。

如果用户拒绝了权限要求,你的app应该采取适当的行动。例如,你的应用程序可能会显示一个对话框,解释为什么它不能执行用户的请求的操作需要该权限。

当系统要求用户授予权限,用户告知系统不要再问了该权限的选项。在这种情况下,任何时间的应用程序使用requestPermissions()再次要求该权限,系统会立即拒绝请求。该系统调用你的onRequestPermissionsResult()回调方法,并传递PERMISSION_DENIED,以同样的方式,将如果用户曾明确再次拒绝你的要求。这意味着,当你调用requestPermissions(),你不能假设与用户进行任何直接的互动已经发生。

参考: Android M新的运行时权限开发者需要知道的一切

https://developer.android.com/training/permissions/requesting.html#perm-request
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  权限问题