Working with System Permissions——Android动态权限处理
声明:本文属于译文,我看了一遍官方文档,读了一遍,把一些重复的没有什么意义的内容简单做了删减。
———————————分割线—————————————
为了保护系统的完整性和用户的隐私,安卓系统对每一个应用程序的都是有一定限制的。
如果应用程序想要使用它外部的资源或信息,该应用程序必须明确请求权限。
根据应用程序的权限类型,该系统可以自动授予该权限,或系统可要求用户授予权限。
这个类演示了如何声明和请求应用程序的权限。
权限声明
每一个安卓程序都受到权限的限制,如果想要使用应用以外的其他的资源,那么程序必须在清单文件中申请相应的权限。
根据权限的敏感程度,系统可以自动授予该权限,或者向用户发送申请权限的请求。
例如,如果你的应用程序请求打开设备的手电筒,系统会自动授予该权限。
但是,如果你的应用程序需要读取用户的联系人,系统会要求用户批准该权限。
根据平台版本,用户在安装应用程序时(在安卓5.1和下)或在运行应用程序时(在安卓6和更高)时给予许可。
确认应用用到的权限
当开发人员在开发一个App的时候,就应该意识到程序需要用到哪些权限
在清单文件添加权限
在 节点下添加
例如,添加一个发送短信的权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application ...>
...
</application>
</manifest>
声明了一个权限以后,系统会判断你申请的权限是否敏感,如果是不影响用户隐私,系统会默认授权,如果访问了用户的敏感信息,系统会想用户申请批准。
在运行时请求权限
从安卓6.0开始,应用每次在运行时应用到了某个权限,都需要想用户发起权限申请,而不是只在安装的时候提示用户一次。
这就简化了安装的过程,用户不需要在安装的时候在意应用开启了哪些权限,而是在运行的时候用户就可以随时控制。
系统的权限分为两类:
正常的
不设计到用户的隐私,系统可以直接默认授权。
危险的
可能会访问到用户的隐私数据,必须用户同意授权以后,应用才可以使用
在任何版本的安卓系统上,应用程序都必须要在清单文件生命用到的权限,但是,这个声明在不同的版本的SDK上会有不同的影响:
如果运行的设备是Android 5.1或者更低的版本,那么在安装的时候,会提示用户应用用到了哪些权限,如果用不不授权,应用是无法安装的。
如果运行的设备是在Android 6.0或者更高,就不会影响应用的安装,那些危险的请求,会在应用用到的时候向用户发起请求,用户可以选择性的授权或者拒绝每一个权限。
检查权限
如果你的程序需要一个危险的权限,都必须要检查是否有这个权限,每次应用在需要这个权限时候,都必须要提示用户是否授权,即使昨天应用已经使用过这个权限,现在还是要向用户再申请一次。
可以用ContextCompat.checkSelfPermission()方法开检查权限
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity, Manifest.permission.WRITE_CALENDAR);
如果程序有这个权限,这个方法会返回 PackageManager.PERMISSION_GRANTED ,如果没有这个权限,方法会返回 PERMISSION_DENIED, 并且会提示用户,是否授权。
请求权限
如果用到了危险权限,必须想用户发起请求授权,安卓也提供了方法,会弹出一个授权的对话框,不能自定义。
解释为什么应用程序需要权限
在某些情况下,你可能需要帮助用户理解为什么你的应用程序需要用到某一个权限,例如一个用户启动一个摄影的应用程序,用户可能对请求相机的权限不会太惊讶,但是用户可能无法理解为什么还要请求联系人,在你请求之前,你应该考虑向用户提供一个解释。记住,不要想这用解释来压倒用户,如果你解释的太多,可能会引起用户的反感而直接卸载了我们的程序。
如果用户一直使用需要某个权限的功能,但是却总是不断的拒绝权限请求,这就可能是用户不理解程序为什么需要这个权限来支持该功能,这种情况下,就应该给用户显示一个解释。
Android提供了一个 shouldshowrequestpermissionrationale()
方法,如果程序发起的权限请求被用户拒绝,该方法会返回true
注意:如果用户之前拒绝了该权限的申请并勾选了
不在提醒
,那么改方法返回false
请求需要的权限
如果你的应用程序之前并没有所需要权限,那么必须要调用requestPermissions()
方法来申请权限,该方法需要设置一个整数类型的请求码,以确保识别是哪个哪个权限的请求,这个方法是异步的操作,会向用户提示授权的对话框,用户响应的结果会有回调,并返回请求码。
以下代码检查应用程序是否具有读取用户联系人的权限,如果没有权限会请求权限:
// 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.
}
}
注意:当你的应用程序调用
requestpermissions()
,系统显示一个标准的对话框给用户。您的应用程序无法配置或更改该对话框。如果你需要向用户提供任何信息或解释,应该在调用requestpermissions()
之前,向用户解释为什么应用程序需要该权限。
处理授权响应
当你的程序发起了权限请求,用户也做出了响应,系统会调用程序的onRequestPermissionsResult()
方法,程序必须要重写这个方法,并通过requestpermissions()
传递的请求码,判断用户是否授权,
例如,一个程序请求READ_CONTACTS
权限:
@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;4/21/2016 5:28:47 PM 4/21/2016 5:28:49 PM
}
// other 'case' lines to check for other
// permissions this app might request
}
}