Android核心主题---activity

以下概述了Android权限的工作方式,包括:如何向用户呈现权限,安装时和运行时权限请求之间的区别,权限的实施方式以及权限及其组的类型。

  • 权限批准

  应用必须通过在应用清单中包含<uses-permission>标记来公布所需的权限,比如请求发送短信的权限:

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

  如果应用在其清单中列出了正常权限(即,不会对用户的隐私或设备操作造成太大风险的权限),系统会自动将这些权限授予您的应用。

  如果应用在其清单中列出了危险权限(即可能会影响用户隐私或设备正常运行的权限),例如上面的SEND_SMS权限,则用户必须明确同意授予这些权限。

  

  如果设备运行的是Android 6.0(API级别23)或更高版本,并且应用程序的targetSdkVersion为23或更高,则在安装时不会通知用户任何应用程序权限。 应用必须要求用户在运行时授予危险权限。 当应用请求权限时,用户会看到一个系统对话框,告诉用户应用尝试访问哪个权限组。 该对话框包括拒绝和允许按钮。如果用户拒绝权限请求,则下次应用请求权限时,该对话框包含一个复选框,选中该复选框后,表示不希望再次提示用户获得权限。

  即使用户授予应用程序所请求的权限,开发者也不能总是依赖它。 用户还可以选择在系统设置中逐个启用和禁用权限。 开发者应该始终在运行时检查并请求权限以防止运行时错误(SecurityException)。如果应用更新包含对其他权限的需求,则会在更新应用之前提示用户接受这些新权限。

  • 可选硬件功能的权限

  访问某些硬件功能(如蓝牙或相机)需要应用程序权限。但是,并非所有Android设备都具有这些硬件功能。因此,如果开发者的应用请求CAMERA权限,那么您还需要在清单中包含<uses-feature>标记来声明是否确实需要此功能。例如:

 1 <uses-feature android:name =“android.hardware.camera”android:required =“false”/> 
  如果开发者为该功能声明了android:required =“false”,那么Google Play允许开发者的应用安装在没有该功能的设备上。然后,开发者必须通过调用PackageManager.hasSystemFeature()检查当前设备是否在运行时具有该功能,并在该功能不可用时正常禁用该功能。

  如果开发者未提供<uses-feature>标记,那么当Google Play看到开发者的应用请求相应的权限时,它会认为开发者的应用需要此功能。因此,它会从没有该功能的设备中过滤开发者的应用,就像开发者在<uses-feature>标记中声明了android:required =“true”一样。

  • 自定义权限

  权限不仅适用于请求系统功能。 应用程序提供的服务可以强制执行自定义权限,以限制谁可以使用它们。

  自定义权限文档链接:https://developer.android.google.cn/guide/topics/permissions/defining

  • 权限的保护级别

  Normal permissions

  此权限涵盖了应用程序需要访问应用程序沙箱外部数据或资源的区域,但用户隐私或其他应用程序操作的风险非常小。 例如,设置时区的权限是正常权限。 如果应用程序在其清单中声明它需要正常权限,则系统会在安装时自动授予应用程序该权限。 系统不会提示用户授予正常权限,用户也无法撤消这些权限。

  Signature permissions

  系统会在安装时授予这些应用程序权限,但仅限于尝试使用权限的应用程序使用与定义权限的应用程序相同的证书进行签名时。(某些签名权限不适用于第三方应用)

  Dangerous permissions  

  危险权限涵盖应用程序需要涉及用户私人信息的数据或资源的区域,或者可能会影响用户存储的数据或其他应用程序的操作。 例如,读取用户联系人的权限是一种危险的权限。 如果应用声明它需要危险权限,则用户必须明确授予该应用的权限。 在用户批准该权限之前,您的应用无法提供依赖该权限的功能。要使用危险权限,您的应用必须提示用户在运行时授予权限。

  

  • 在运行时请求权限

  如果设备运行的是 Android 5.1 或更低版本,或者应用的目标 SDK 为 22 或更低:如果您在清单中列出了危险权限,则用户必须在安装应用时授予此权限;如果他们不授予此权限,系统根本不会安装应用。

  如果设备运行的是 Android 6.0 或更高版本,或者应用的目标 SDK 为 23 或更高:应用必须在清单中列出权限,并且它必须在运行时请求其需要的每项危险权限。用户可以授予或拒绝每项权限,且即使用户拒绝权限请求,应用仍可以继续运行有限的功能。

  1、检查权限

  如果您的应用需要危险权限,则每次执行需要这一权限的操作时您都必须检查自己是否具有该权限。用户始终可以自由调用此权限,因此,即使应用昨天使用了相机,它不能假设自己今天仍具有该权限。

要检查您是否具有某项权限,请调用 ContextCompat.checkSelfPermission() 方法。例如,以下代码段显示了如何检查 Activity 是否具有在日历中进行写入的权限:

1 // Assume thisActivity is the current activity
2 int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
3         Manifest.permission.WRITE_CALENDAR);

  如果应用具有此权限,方法将返回 PackageManager.PERMISSION_GRANTED,并且应用可以继续操作。如果应用不具有此权限,方法将返回 PERMISSION_DENIED,且应用必须明确向用户要求权限。

  2、向用户解释为什么需要权限

  在某些情况下,您可能需要帮助用户了解您的应用为什么需要某项权限。例如,如果用户启动一个摄影应用,用户对应用要求使用相机的权限可能不会感到吃惊,但用户可能无法理解为什么此应用想要访问用户的位置或联系人。在请求权限之前,不妨为用户提供一个解释。请记住,您不需要通过解释来说服用户;如果您提供太多解释,用户可能发现应用令人失望并将其移除。您可以采用的一个方法是仅在用户已拒绝某项权限请求时提供解释。如果用户继续尝试使用需要某项权限的功能,但继续拒绝权限请求,则可能表明用户不理解应用为什么需要此权限才能提供相关功能。对于这种情况,比较好的做法是显示解释。为了帮助查找用户可能需要解释的情形,Android 提供了一个实用程序方法,即 shouldShowRequestPermissionRationale()。如果应用之前请求过此权限但用户拒绝了请求,此方法将返回 true

  3、请求需要的权限

  如果您的应用需要应用清单中列出的危险权限,那么,它必须要求用户授予该权限。Android 为您提供了多种权限请求方式。调用这些方法将显示一个标准的 Android 对话框,不过,您不能对它们进行自定义。

  如果应用尚无所需的权限,则应用必须调用一个 requestPermissions() 方法,以请求适当的权限。应用将传递其所需的权限,以及您指定用于识别此权限请求的整型请求代码。此方法异步运行:它会立即返回,并且在用户响应对话框之后,系统会使用结果调用应用的回调方法,将应用传递的相同请求代码传递到 requestPermissions()

  举例:以下代码可以检查应用是否具备读取用户联系人的权限,并根据需要请求该权限:

 1 // Here, thisActivity is the current activity
 2 if (ContextCompat.checkSelfPermission(thisActivity,
 3                 Manifest.permission.READ_CONTACTS)
 4         != PackageManager.PERMISSION_GRANTED) {
 5 
 6     // Should we show an explanation?
 7     if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
 8             Manifest.permission.READ_CONTACTS)) {
 9 
10         // Show an expanation to the user *asynchronously* -- don't block
11         // this thread waiting for the user's response! After the user
12         // sees the explanation, try again to request the permission.
13 
14     } else {
15 
16         // No explanation needed, we can request the permission.
17 
18         ActivityCompat.requestPermissions(thisActivity,
19                 new String[]{Manifest.permission.READ_CONTACTS},
20                 MY_PERMISSIONS_REQUEST_READ_CONTACTS);
21 
22         // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
23         // app-defined int constant. The callback method gets the
24         // result of the request.
25     }
26 }

  4、处理权限请求响应

  当应用请求权限时,系统将向用户显示一个对话框。当用户响应时,系统将调用应用的 onRequestPermissionsResult() 方法,向其传递用户响应。您的应用必须替换该方法,以了解是否已获得相应权限。回调会将您传递的相同请求代码传递给 requestPermissions()。例如,如果应用请求 READ_CONTACTS 访问权限,则它可能采用以下回调方法:

 1 @Override
 2 public void onRequestPermissionsResult(int requestCode,
 3         String permissions[], int[] grantResults) {
 4     switch (requestCode) {
 5         case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
 6             // If request is cancelled, the result arrays are empty.
 7             if (grantResults.length > 0
 8                 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
 9 
10                 // permission was granted, yay! Do the
11                 // contacts-related task you need to do.
12 
13             } else {
14 
15                 // permission denied, boo! Disable the
16                 // functionality that depends on this permission.
17             }
18             return;
19         }
20 
21         // other 'case' lines to check for other
22         // permissions this app might request
23     }
24 }

  系统显示的对话框说明了您的应用需要访问的权限组;它不会列出具体权限。例如,如果您请求 READ_CONTACTS 权限,系统对话框只显示您的应用需要访问设备的联系人。用户只需要为每个权限组授予一次权限。如果您的应用请求该组中的任何其他权限(已在您的应用清单中列出),系统将自动授予应用这些权限。例如,假设您在应用清单中列出了 READ_CONTACTS 和 WRITE_CONTACTS。如果您请求 READ_CONTACTS 且用户授予了此权限,那么,当您请求 WRITE_CONTACTS 时,系统将立即授予您该权限,不会与用户交互。

猜你喜欢

转载自www.cnblogs.com/adapter/p/9467197.html