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