【发布时间】:2015-11-15 01:02:13
【问题描述】:
假设你有这样的方法:
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 android.permission.WRITE_EXTERNAL_STORAGE 或其他权限,一切都会好起来的。
但在新的 Marshmallow (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) 必须筛选出 permission 请求它们实际上是 responding to,无论用户是否说是或否(据我所知,没有办法处理“不”与“不,不要再问”),(6)首先弄清楚他们试图完成的事情,这促使整个要求-permissions 过程,以便程序最终 (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(产品经理):“啊-我想-有一个-可能有同步响应的选项--”
Norbye:“哦。那会让事情发生——”
Poiesz:“我可以在内部与人交谈。我记得有一次关于同步的讨论——但我们可以找到答案。”
Norbye:“是的。事实上,我们可能应该把它变成工具。在那里你有一个简单的重构......”
然后他谈到在工具中使用注释来确定哪些 API 需要权限..(到目前为止,这在 IMO 中还没有那么好用),以及他希望有朝一日这些工具在发现未经检查的“危险”方法调用:
Norbye:“...如果你也在 M不是,我们会说“你可能需要做一些事情来请求这里的许可”。不过,我想要的是有一个快速修复,你可以去“CHING!”它插入了所有正确的东西来询问,但是当我看到事情的时候,这需要重组很多东西——添加接口和回调,改变流程,而我们做不到。但如果有一个简单的同步模式作为临时的东西或永久的东西,那会[很棒]。"
【问题讨论】:
-
我认为 UI 线程阻塞不会有问题。甚至在 Marshmallow 之前,我们就做了很多询问对话框并调用不同的代码取决于用户的决定,所有这些都是异步的。
-
您认为同步方法如何工作?如果不能只单击 UI 线程。现在的事情实际上非常简单,只需几行代码。我想一个同步选项实际上更复杂。结果只是更多的代码聚集在一个地方,而不是现在处理事情的好方法。
-
归根结底就是为您的应用程序提供一个干净整洁的设计和架构,我发现运行时权限可以很好地集成到整个系统中,即使我希望关键方法不会成为其中的一部分
Activity类。但是我可以想象出一些很好的理由来说明为什么会出现这种情况。 -
顺便说一句:Android Studio 中有快速修复插入运行时权限检查。而且我从来不需要重组任何东西来整合它们。
-
如果您足够幸运已经拥有需要异步权限的代码,事情就很简单了。但是我给出了一些示例,其中可能没有考虑到应用程序的设计,例如返回成功/失败的方法,该方法可能在整个应用程序的无数上下文中重复调用。它必须完全重构。传递大量“权限请求响应”代码,即。每种类型的权限检查的上下文,通过 result 方法,然后始终正确处理每个场景(每个实例、每个权限、每个结果)可以轻松地将代码快速变成意大利面条。
标签: android android-permissions android-6.0-marshmallow