根据这个:http://developer.android.com/preview/features/runtime-permissions.html#coding应用程序可以检查运行时权限和请求权限(如果尚未授予它) . 然后将显示以下对话框:
如果用户拒绝重要权限,则应用程序应显示解释为何需要权限以及拒绝具有何种影响的解释 . 该对话框有两个选项:
-
再次重试(再次请求许可)
-
拒绝(app将在没有该权限的情况下工作) .
但是,如果用户检查 Never ask again
,则不应显示带有解释的第二个对话框,尤其是如果用户之前已经拒绝过一次 . 现在的问题是:我的应用程序如何知道用户是否已检查 Never ask again
? IMO onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
没有给我这些信息 .
第二个问题是:Google是否计划在权限对话框中添加自定义消息,以解释应用程序需要权限的原因?那样就永远不会有第二个对话框,肯定会有更好的ux .
23 回答
开发人员预览版2对应用程序请求权限的方式进行了一些更改(另请参阅http://developer.android.com/preview/support.html#preview2-notes) .
第一个对话框现在看起来像这样:
没有“Never again again”复选框(与开发者预览1不同) . 如果用户拒绝该权限,并且该权限对于该应用程序至关重要,则可以提供另一个对话框来解释该应用程序要求该权限的原因,例如:像这样:
如果用户再次拒绝该应用程序应该关闭,如果它绝对需要该权限或继续运行有限的功能 . 如果用户重新考虑(并选择重试),则再次请求权限 . 这次提示符如下所示:
第二次显示“永不再询问”复选框 . 如果用户再次拒绝并且勾选了复选框,则不会再发生任何事情 . 是否勾选了复选框可以通过使用Activity.shouldShowRequestPermissionRationale(String)来确定,例如,像这样:
这就是Android文档所说的内容(https://developer.android.com/training/permissions/requesting.html):
要知道用户是否使用"never ask again"拒绝,您可以在用户未授予权限时再次检查onRequestPermissionsResult中的shouldShowRequestPermissionRationale方法 .
您可以使用以下代码打开您的应用设置:
无法将用户直接发送到“授权”页面 .
您可以在
onRequestPermissionsResult()
中查看shouldShowRequestPermissionRationale()
.https://youtu.be/C8lUdPVSzDk?t=2m23s
检查是否在
onRequestPermissionsResult()
中授予了权限 . 如果 not 则检查shouldShowRequestPermissionRationale()
.如果此方法返回
true
,则显示为何需要此特定权限的说明 . 然后再次根据用户的选择requestPermissions()
.如果它返回
false
,则显示一条错误消息,表明未授予权限,app无法继续进行或禁用某项特定功能 .以下是示例代码 .
显然,谷歌 Map 正是这样做的位置许可 .
这是检查当前权限状态的一种简单方法:
警告:在用户通过用户提示接受/拒绝权限之前,在第一个应用程序启动时返回BLOCKED_OR_NEVER_ASKED(在sdk 23设备上)
Update:
Android支持库现在似乎也有一个非常相似的类
android.support.v4.content.PermissionChecker
,其中包含checkSelfPermission()
,它返回:你 can determine 检查是否要在
onRequestPermissionsResult()
回调方法中显示权限 rationale . 如果您发现任何权限设置为 never ask again ,则可以请求用户从设置中授予权限 .我的完整实现如下 . 它适用于 single 或 multiple 权限要求 . 使用以下或directly use my library.
可能对某人有用: -
What I have noticed is, if we check the shouldShowRequestPermissionRationale() flag in to onRequestPermissionsResult() callback method, it shows only two states .
状态1: - 返回true: - 用户单击拒绝权限(包括第一次)的任何时间 .
状态2: - 返回错误: - 如果用户选择“永不再问” .
Link of detailed working example
一旦用户标记为“不再询问”,则无法再次显示该问题 . 但是可以向用户解释他先前已拒绝许可并且必须在设置中授予权限 . 并使用以下代码引用他的设置:
如果您想要检测所有“状态”(第一次被拒绝,被拒绝,被拒绝“永不再问”或被永久拒绝),您可以执行以下操作:
创建2个布尔值
在请求许可之前设置第一个:
在onRequestPermissionsResult方法中设置第二个:
使用以下“表”在onRequestPermissionsResult()中执行您需要的任何操作(在检查您仍然没有权限之后):
我有同样的问题,我想出来了 . 为了简化生活,我编写了一个util类来处理运行时权限 .
PreferenceUtil方法如下 .
现在,您只需要使用方法* checkPermission *和适当的参数 .
这是一个例子,
如果用户选中 Never ask again ,您将获得onPermissionDisabled的回调 .
快乐编码:)
Complete explanation for every case of permission
我在Android M中写了一个权限请求的简写 . 此代码还处理旧版Android版本的向后兼容性 .
所有丑陋的代码都被提取到一个片段中,片段将自身附加到请求权限的Activity上 . 您可以使用
PermissionRequestManager
如下:看一看:https://gist.github.com/crysxd/385b57d74045a8bd67c4110c34ab74aa
方法shouldShowRequestPermissionRationale()可以是用户检查用户是否选择了'never asked again'选项并拒绝了该权限 . 有很多代码示例,所以我宁愿解释如何将它用于这样的目的,因为我认为它的名称及其实现使它实际上变得更加复杂 .
如Requesting Permissions at Run Time中所述,如果选项'never ask again'可见,则该方法返回true,否则返回false;因此它在第一次显示对话框时返回false,然后从第二次开始返回true,并且只有当用户拒绝选择该选项的权限时,此时它才会再次返回false .
要检测这种情况,您可以检测序列false-true-false,或者(更简单)您可以使用一个标记来跟踪显示对话框的初始时间 . 之后,该方法返回true或false,其中false将允许您检测何时选择该选项 .
试试这个简单的权限库 . 它将通过3个简单步骤处理与权限相关的所有操作 . 它节省了我的时间 . You can finish all permission related work in 15 mins .
它可以处理Deny,它可以处理Never never再次询问,它可以调用app设置以获得权限,它可以给出一条Rational消息,它可以给出一个Denial消息,它可以给出一个已接受权限的列表,它可以给出一个被拒绝的列表权限等
https://github.com/ParkSangGwon/TedPermission
Step 1: 添加您的依赖项
Step2: 询问权限
Step 3: 处理权限响应
一个有用的函数,用于确定是否已阻止任意权限请求(在Kotlin中):
使用此功能需要在首次请求权限时将共享首选项布尔值与所需权限(例如
android.Manifest.permission.READ_PHONE_STATE
)的名称设置为true
.说明:
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
因为某些代码只能在API级别23上运行 .ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED
检查我们还没有获得许可 .!activity.shouldShowRequestPermissionRationale(permission)
检查用户是否已拒绝该应用再次询问 . 由于quirks of this function,还需要以下行 .PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(permission, false)
使用此方法(以及在第一个权限请求时将值设置为true)以区分"Never asked"和"Never ask again"状态,因为前一行不返回此信息 .对于这个解决方案,请不要向我扔石头 .
这有效,但有点“hacky” .
当您拨打
requestPermissions
时,请注册当前时间 .然后在
onRequestPermissionsResult
如果未授予结果,请再次检查时间 .
由于用户确实无法点击这么快拒绝按钮,我们知道他选择“永不再问”,因为回调是即时的 .
使用风险自负 .
您可以使用
内
请参阅以下示例:
Check if it has permission when the user clicks the button:
When the user answer the permission dialog box we will go to onRequestPermissionResult:
你可以听得很漂亮 .
Listener
MainClass for permission
Used by this way
override onRequestPermissionsResult in activity or fragmnet
我还想获得用户是否选择“永不再问”的信息 . 我已经实现了一个带有丑陋外观的“几乎解决方案”,但在我告诉你如何之前,我会告诉你我的动机:
我想最初提供权限引用功能 . 如果用户使用它并且没有权限,他/她将获得上面的第1个对话框或第2个和第3个对话框 . 当用户选择“永不再问”时,我想禁用该功能并以不同方式显示它 . - 我的动作是由一个微调文本条目触发的,我还想在显示的标签文本中添加'(Permission revoked)' . 这向用户显示:“由于我的权限设置,有功能但我无法使用它 . ”但是,这似乎不可能,因为我无法检查是否已经选择了“永不再问” .
我通过主动权限检查启用了我的功能,从而找到了我可以忍受的解决方案 . 我在onRequestPermissionsResult()中显示Toast消息,如果是否定响应,但仅当我没有显示我的自定义原理弹出窗口时 . 因此,如果用户选择了“永不再问”,他只会收到一个祝酒词 . 如果用户不愿意选择“永不再问”,他只能获得操作系统弹出的自定义原理和权限请求,而不是吐司,因为连续三个通知会太麻烦 .
相反,当您在
shouldShowRequestPermissionRationale()
处于错误状态时再次请求权限时,您将收到onRequestPermissionsResult()
上的回调作为PERMISSION_DENIED来自Android doc:
当系统要求用户授予权限时,用户可以选择告知系统不要再次请求该权限 . 在这种情况下,只要应用程序使用
requestPermissions()
再次请求该权限,系统就会立即拒绝该请求 . 系统调用onRequestPermissionsResult()
回调方法并传递PERMISSION_DENIED
,就像用户再次明确拒绝您的请求一样 . 这意味着当您调用requestPermissions()
时,您不能假设已经发生了与用户的任何直接交互 .我必须实现相机的动态权限 . 如果发生3种可能的情况:1 . 允许,2 . 拒绝,3 . 不要再问 .
您可以使用
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)
方法来检测是否从未询问过 .如需更多参考:Check this
要检查多个权限,请使用:
explain()方法
上面的代码也会显示对话框,它会将用户重定向到应用程序设置屏幕,如果已经选中,则可以给予许可,从不再询问按钮 .
扩展 mVck 上面的答案,以下逻辑确定是否已针对给定的权限请求检查了"Never ask again":
摘自下方(完整示例见answer)
你可以阅读android官方文档Request App Permissions
或者你可以在Github上找到许多流行的Android权限库
PermissionsDispatcher
RxPermissions
easypermissions