android - 您可以在 Android Marshmallow (API 23) 的运行时权限模型中同步请求权限吗?

标签 android android-permissions android-6.0-marshmallow

假设你有一个这样的方法:

public boolean saveFile (Url url, String content) {

   // save the file, this can be done a lot of different ways, but
   // basically the point is...

   return save_was_successful;
}

在整个应用程序中,如果您想将文件保存到外部存储,您可以执行类似...
if (saveFile(external_storage_url, "this is a test")) {
   // yay, success!
} else { // notify the user something was wrong or handle the error }

这是一个简化的例子,所以不要在我的情况下阻止 UI,正确处理异常等。如果你不喜欢文件保存,你可以想象一个 getContact()getPhoneState()管他呢。关键是它是一个需要权限的操作,它返回一些值,并在整个应用程序中使用。

在 Android <= Lollipop 中,如果用户已安装并同意授予 android.permission.WRITE_EXTERNAL_STORAGE或者别的什么,一切都会好的。

但是在新的棉花糖 (API 23) 中 runtime permission model , 在您可以将文件保存到外部存储之前,您应该 (1) 检查是否已授予权限。 If not , 可能 (2) show a rationale for the request (如果 system thinks it's a good idea )祝酒或其他任何东西和(3)要求用户通过对话框授予权限,然后基本上坐下来等待回调......

(所以你的应用程序坐在那里,等待......)

(4) 当用户最终响应对话框时,onRequestPermissionsResult()方法触发,您现在的代码 (5) 必须筛选 WHICH permission要求他们实际上是 responding to ,无论用户说是或否(据我所知,没有办法处理“不”与“不,不要再问”),(6) 弄清楚他们首先试图完成的提示是什么整个请求权限过程,以便程序最终可以 (7) 继续执行该操作。

要了解用户在步骤 (6) 中尝试执行的操作涉及先前已通过特殊的 code (“权限请求响应”)在文档中被描述为 permission request 类型的标识符(相机/联系人/等)但在我看来更像是“特别是当您意识到需要请求权限时您正在尝试做的事情”代码,因为相同的权限/组可能用于多个在您的代码中使用目的,因此您需要在获得许可后使用此代码将执行返回到适当的位置。

我可能完全误解了这应该如何工作 - 所以如果我离开了,请告诉我 - 但更重要的是我真的不知道如何考虑使用上述所有内容saveFile()由于异步“等待用户响应”部分,前面描述的方法。我考虑过的想法非常老套,而且肯定是错误的。

今天的 Android Developer Podcast暗示可能有一种同步解决方案即将到来,甚至有人谈到了 Android Studio 中一种神奇的、一步式 alt-enter 类型的“添加权限请求”工具。尽管如此,运行时权限过程可能如何被插入 saveFile()或者别的什么——我在想一些事情:
public boolean saveFile(Url url, String content) {
   //   this next line will check for the permission, ask the user
   //   for permission if required, maybe even handle the rationale
   //   situation
   if (!checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        R.string.permission_storage_rationale))
       {
           return false; // or throw an exception or whatever
       } else {

   // try to save the file

   return save_was_successful;

   }
}

所以上面的checkPermission()如果用户没有并且拒绝授予权限,则会失败。也许可以在 checkPermission() 周围使用循环尝试最多询问 3 次或其他什么,或者更好的是,如果该方法处理了一个理智的不要惹人厌的政策。

这样的事情可能吗?可取?任何这样的解决方案会阻止 UI 线程吗?从播客看来,谷歌可能有这样的解决方案即将到来,但我想知道是否有什么东西——一个便利类,一个模式,什么东西——不需要每个人都必须重构所有需要许可的操作,我必须假设这可能会变得非常困惑。

抱歉这个冗长的问题,但我想尽可能完整。我将取消我的回答。谢谢!

更新 :这是上述播客的成绩单。

收听关于 41:20 .在本次讨论中:

粗略抄录:

Tor Norbye(工具团队):“所以对于开发人员来说,这似乎不应该是很多工作。但我理解部分问题在于这些不是同步调用,对吧?。所以你必须 - 实际上改变你的 Activity 的编写方式,让它有一个回调——所以它真的有点像一个状态机......对于这个状态,你——”

Poiesz(产品经理):“啊——我想——有一个——可能有一个同步响应的选项——”

诺拜:“哦。那会让事情——”

Poiesz:“我可以与内部人员交谈。我记得有一次关于同步的讨论——但我们可以找到答案。”

Norbye:“是的。事实上,我们可能应该将它纳入工具中。如果你有一个简单的重构......”

然后他谈到在工具中使用注释来确定哪些 API 需要权限..(到目前为止,IMO 的工作方式不是很好),以及他希望工具有一天能够在发现未经检查的“危险”代码时实际生成所需的代码"方法调用:

Norbye:“......那么如果你也在 M 上,它会说,'嘿,你真的在​​检查这个权限还是你在捕捉安全异常?',如果你不是,我们会说“你可能需要做一些事情来请求这里的许可。”但我想要的是快速修复,你可以去'CHING!'它插入了所有正确的东西来询问,但是当我看到时,事情又回来了,这需要重构很多东西——添加接口(interface)和回调,并改变流程,这是我们做不到的。但如果有一个简单的同步模式作为临时或永久的东西,那会[很棒]。”

最佳答案

至于棉花糖,我的理解是你不能。

我必须在我的应用程序中解决同样的问题。这是我如何做到的:

  • 重构 :将依赖于某种权限的每一块代码移动到它自己的方法中。
  • 更多重构 :确定每种方法的触发器(例如启动 Activity 、点击控件等)并将具有相同触发器的方法组合在一起。 (如果两个方法最终具有相同的触发器并且需要相同的权限集,请考虑合并它们。)
  • 更多重构 : 找出什么依赖于之前被调用的新方法,并确保它在调用这些方法时是灵活的:要么将它移到方法本身中,要么至少确保无论你做什么都不会抛出异常,如果您的方法之前没有被调用过,并且一旦调用该方法,它就会开始按预期运行。
  • 请求代码 :对于这些方法中的每一个(或其组),定义一个整数常量以用作请求代码。
  • 检查和请求权限 :将这些方法/方法组中的每一个包装成以下代码:

  • .
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.SOME_PERMISSION) == PackageManager.PERMISSION_GRANTED)
        doStuffThatRequiresPermission();
    else
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.SOME_PERMISSION}, Const.PERM_REQUEST_DO_STUFF_THAT_REQUIRES_PERMISSION);
    
  • 处理响应 : 为 onRequestPermissionsResult() 编写一个实现在每个 Activity要求权限。检查请求的权限是否被授予,并使用请求代码来确定需要调用什么方法。

  • 请注意,该 API 需要 Activity用于运行时权限请求。如果您有非交互式组件(例如 Service ),请查看 How to request permissions from a service in Android Marshmallow有关如何解决此问题的建议。基本上,最简单的方法是显示一个通知,然后显示一个 Activity它只显示运行时权限对话框。 Here是我在我的应用程序中解决这个问题的方法。

    关于android - 您可以在 Android Marshmallow (API 23) 的运行时权限模型中同步请求权限吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32134299/

    相关文章:

    java - 我需要帮助理解 java.lang.StringIndexOutOfBoundsException

    android - 拒绝对特定库/模块的权限

    android - getAllNetworkInfo() 在 M 中已弃用,但其替代品具有不同的行为

    android - 在另一个背景中创建背景

    android - 如何使用 IDA Pro 调试 apk 中的 *.so?

    onRequestPermissionsResult 中的 java.lang.StackOverflowError (Android)

    Android权限清理

    自 Android 6 Marshmallow 以来,javax.crypto.Cipher 的工作方式有所不同

    android - 显示摄像头 Intent 仅在Android中的Webview中?无法仅获取Camera Intent?android 5+和6+

    android - 为什么我的新资源没有添加到 R 类中显示的 res/子文件夹中?