【Android training】使用系统权限

来源:互联网 发布:lol显示网络连接异常 编辑:程序博客网 时间:2024/05/22 17:17

使用系统权限 原文链接

 

为了保护系统的完整性和用户的隐私,Android在有限的访问“沙箱”中运行每个应用。如果应用程序想要使用“沙箱”外的资源或资讯,应用程序必须明确要求许可。根据应用请求的权限类型,系统可以自动授予权限,或者系统可能会要求用户授予权限。

 

声明权限

 

根据许可的敏感程度,系统可能自动授予权限,或者请求用户授予该权限。例如,如果您的应用程序请求打开设备手电筒的权限,系统将自动授予该权限。但如果您的应用需要阅读用户的联系人,系统会要求用户批准该权限。根据平台版本,用户在安装应用程序(Android 5.1.1及更低版本)或运行应用程序时(Android 6.0及更高版本)授予权限。

 

确定您的应用程序需要哪些权限

在您开发应用程序时,应注意您的应用程序何时使用需要权限的功能。通常,只要应用程序使用应用程序未创建的信息或资源,或执行影响设备或其他应用程序的行为的操作,应用程序将需要权限。例如,如果应用需要访问互联网,请使用设备相机,或打开或关闭Wi-Fi,该应用需要适当的许可。

您的应用程序直接执行的操作可能需要权限。但如果使用intent请求其他应用执行任务或提供信息,则您的应用不需要权限。例如,如果您的应用需要阅读用户的通讯录,则该应用需要READ_CONTACTS权限。但是,如果您的应用程序使用intent从用户的联系人应用程序请求信息,则您的应用程序不需要任何权限,但联系人应用需要具有该权限。

 

在Manifest 中添加权限

要声明您的应用程序需要权限,请将<uses-permission>元素放在应用程序清单中,作为顶层<manifest>元素的子代。 例如,需要发送短信的应用程序将在清单中显示此行:

<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>

声明权限后系统的行为取决于许可的敏感度。如果权限不影响用户隐私,系统会自动授予权限。如果权限可能授予对敏感用户信息的访问权限,系统将要求用户批准该请求。有关不同类型权限的更多信息,请参阅正常和危险权限。

在运行时请求权限

从Android 6.0(API级别23)开始,用户在应用运行时向用户授予权限,而不是安装应用的时候。这种方法简化了应用程序安装过程,因为用户在安装或更新应用程序时不需要授予权限。它还使用户能够更好地控制应用程序的功能; 例如,用户可以选择给相机应用程序访问相机而不是设备位置。用户可以随时撤销权限,方法是转到应用的“设置”屏幕。

 

系统权限分为两类,正常和危险:

 

普通权限不会直接危及用户的隐私。 如果您的应用程序在其清单中列出了正常的权限,系统会自动授予权限。

 

危险的权限可以让应用程序访问用户的机密数据。 如果您的应用程序在其清单中列出了正常的权限,系统会自动授予权限。如果您列出危险的许可,用户必须明确地批准您的应用程序。

 

在所有版本的Android上,您的应用程序需要声明其应用程序清单中所需的正常和危险权限,但是,该声明的效果因系统版本和应用程序的目标SDK级别而异:

 

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

 

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

注意:从Android 6.0(API级别23)开始,用户可以随时撤销应用程序权限。您应该测试您的应用程序,在缺少所需权限的情况下验证其是否正常运行。

 

检查权限

如果您的应用程序需要危险的权限,则必须检查每次执行需要该权限的操作时是否具有该权限。因为用户可以随时撤销权限,所以即使上一次运行正常,下一次运行还是需要检查权限。要检查是否有权限,请调用ContextCompat.checkSelfPermission()方法。

例如,此代码段显示如何检查活动是否有权写入日历:

// Assume thisActivity is the current activityint permissionCheck = ContextCompat.checkSelfPermission(thisActivity,        Manifest.permission.WRITE_CALENDAR);

如果应用程序有权限,该方法返回PackageManager.PERMISSION_GRANTED,并且应用程序可以继续操作。 如果应用程序没有权限,该方法返回PERMISSION_DENIED,并且应用程序必须明确地要求用户许可。

 

请求权限

如果您的应用需要应用清单中列出的危险许可,则必须要求用户授予权限。 Android提供了几种可用于请求权限的方法。调用这些方法会出现一个标准的Android对话框,您无法自定义。

 

为什么应用程序需要这些权限

在某些情况下,您可能希望帮助用户了解您的应用程序需要许可的原因。例如,如果用户启动摄影应用程序,用户可能不会惊讶于应用程序要求使用摄像头的权限,但用户可能不了解应用程序要访问用户位置或联系人的原因。在您请求许可之前,您应该考虑向用户提供说明。请记住,不要太多的说明,这样用户会反感而删除应用。

 

您可能使用的一种方法是仅在用户已经拒绝该权限请求时提供说明。如果用户不断尝试使用需要权限的功能,但是不断关闭权限请求,这可能表明用户不明白为什么应用程序需要提供该功能的权限。在这样的情况下,显示一个解释可能是一个好主意。

 

为了帮助找到用户可能需要解释的情况,Android提供了一个utiltity方法,shouldShowRequestPermissionRationale()。 如果应用程序以前请求了此权限,并且用户拒绝了该请求,则此方法将返回true。

注意:如果用户拒绝了过去的权限请求,并在权限请求系统对话框中选择了不再询问选项,则此方法返回false。如果设备策略禁止应用拥有该权限,该方法也将返回false

 

请求你需要的权限

如果您的应用程序尚未拥有所需的权限,则应用程序必须调用其中一个requestPermissions()方法来请求相应的权限。您的应用程序会传递所需的权限,还可以指定您指定的整数请求代码,以识别此权限请求。该方法异步运行,它立即返回,用户响应对话框后,系统把结果传递给回调方法,并传递给回调方法和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 explanation 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;        }        // other 'case' lines to check for other        // permissions this app might request    }}

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

 

例如,假设您的应用程序清单中列出了READ_CONTACTS和WRITE_CONTACTS。如果您请求READ_CONTACTS并且用户授予权限,然后请求WRITE_CONTACTS,则系统将立即授予您该权限,而无需与用户交互。

如果用户拒绝许可请求,您的应用程序应该采取适当的措施。例如,您的应用程序可能会显示一个对话框,说明为什么无法执行需要该权限的用户请求的操作。

 

当系统要求用户授予权限时,用户可以选择告诉系统不再请求该权限。在这种情况下,任何应用程序使用requestPermissions()再次请求该权限,系统将立即拒绝该请求。系统调用您的onRequestPermissionsResult()回调方法并通过PERMISSION_DENIED,与用户再次明确拒绝您的请求相同。 这意味着当您调用requestPermissions()时,您不能假定与用户发生任何直接交互,也可能是系统直接调用了回调方法。

 

权限使用注意事项

一个应用程序如果请求的权限太多,用户可能会感到反感。或者用户担心应用程序可能在使用该用户的信息,用户可能会卸载应用程序。以下最佳做法可以帮助您避免这样糟糕的用户体验。

 

考虑使用Intent

在许多情况下,您可以通过两种方式为应用程序执行任务。您可以让您的应用程序请求执行操作本身的权限。或者,您可以让应用程式使用其他应用程式执行任务。

 

例如,假设您的应用程序需要能够使用设备摄像头拍摄照片。您的应用程序可以请求CAMERA权限,允许您的应用直接访问相机。然后,您的应用程序将使用相机API来控制相机并拍摄照片。这种方法使您的应用程序可以完全控制摄影过程,并且可以将摄像头UI整合到应用程序中

 

但是,如果您不需要这样的完全控制,则可以使用ACTION_IMAGE_CAPTURE意图请求映像。当您发送意图时,系统提示用户选择相机应用程序(如果还没有默认的相机应用程序)。用户使用所选的相机应用拍摄照片,该应用程序会将照片返回到您的应用程序的onActivityResult()方法。

 

同样,如果您需要拨打电话,访问用户的联系人等等,您可以通过创建适当的意图来完成此操作,也可以直接请求权限并访问相应的对象。每种方法都有优缺点

 

如果你使用权限

执行操作时,您的应用程序可以完全控制用户体验。 但是,由于您需要设计合适的UI,因此广泛的控制会增加您的任务的复杂性。

 

在运行时或安装时间(取决于用户的Android版本),系统将提示用户授予权限。 之后,您的应用程序可以执行操作,而不需要用户的额外交互。 但是,如果用户未授予权限(或稍后撤销),您的应用程序将无法完成该操作。

 

如果你使用intent

您不必为设计UI。 处理意图的应用程序提供了UI。 但是,这意味着您无法控制用户体验。 用户可能会与您从未见过的应用互动。

 

如果用户没有该操作的默认应用程序,系统会提示用户选择一个应用程序。 如果用户没有指定默认处理程序,则每次执行操作时,它们可能需要经过一个额外的对话框。

 

只请求你需要的权限

每次您要求许可时,强制用户作出决定。您应该尽量减少进行这些请求的次数。如果用户运行Android 6.0(API级别23)或更高版本,每次用户尝试一些需要许可的新应用程序功能时,应用程序必须通过权限请求中断用户的工作。如果用户运行的是早期版本的Android,则用户必须在安装该应用时授予每个应用的权限; 如果列表太长或似乎不合适,用户可能会决定不安装您的应用程序。由于这些原因,您应该尽可能减少应用程序所需的权限数量。

 

您的应用程序通常可以通过使用意图来避免请求许可。如果功能不是应用功能的核心部分,则应考虑将工作交给另一个应用程序,如“使用意图”中所述。

 

解释你为什么需要这些权限

当您调用requestPermissions()时,系统显示的权限对话框显示您的应用程序需要什么权限,但不能说明为什么。在某些情况下,用户可能会发现困惑。向用户解释为什么您的应用程序想要在调用requestPermissions()之前的权限是个好主意,

例如,摄影应用程序可能想要使用位置服务,以便它可以对照片进行地理标记。一个典型的用户可能不明白照片可能包含位置信息,并且会让他们的摄影应用程序想知道位置的原因困惑不解。所以在这种情况下,应用程序在调用requestPermissions()之前告诉用户这个功能是一个好主意,

通知用户的一种方法是将这些请求合并到应用程序教程中。教程可以依次显示每个应用程序的功能,因此可以解释需要哪些权限。例如,摄影应用程序的教程可以展示其“与您的联系人分享照片”功能,然后告诉用户他们需要授予该应用的权限才能看到用户的联系人。然后,应用程序可以调用requestPermissions()来询问用户的访问权限。当然,并不是每个用户都将遵循本教程,因此您仍然需要在应用程序正常运行期间检查并请求权限

 

测试两种权限模式

使用Android 6.0(API级别23)开始,用户在运行时授予和撤消应用程序权限,而不是在安装应用程序时执行此操作。因此,您必须在更广泛的条件下测试您的应用程序。在Android 6.0之前,您可以合理地假设,如果您的应用程序正在运行,它具有在应用程序清单中声明的所有权限。在新的权限模型下,您将无法再做出这样的假设

 

以下提示将帮助您识别运行在API级别23或更高版本的设备上与权限相关的代码问题:

确定您的应用程序的当前权限和相关的代码路径。

测试用户流经受权限保护的服务和数据。

使用许可或撤销权限的各种组合进行测试。 例如,相机应用程序可能会在其清单中列出CAMERA,READ_CONTACTS和ACCESS_FINE_LOCATION。 您应该测试应用程序,其中的每个权限打开和关闭,以确保该应用程序可以正常处理所有权限配置。 请记住,从Android 6.0开始,用户可以为任何应用启用或关闭权限,即使是针对API级别为22或更低的应用。

使用adb工具从命令行管理权限:

按组列出权限和状态:

$ adb shell pm list permissions -d –g

授予或撤销一个或多个权限:

$ adb shell pm [grant|revoke] <permission-name>

分析您的应用程序的使用权限的服务。

 







原创粉丝点击