您可以在Android Marshmallow(API 23)的运行时权限模型中同步请求权限吗? [英] Can you request permissions synchronously in Android Marshmallow (API 23)'s runtime permissions model?

查看:63
本文介绍了您可以在Android Marshmallow(API 23)的运行时权限模型中同步请求权限吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Say you have a method like this:

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

在整个应用程序中,如果要将文件保存到外部存储中,请执行以下操作...

Throughout your app, if you want to save a file to external storage, you do something like...

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()或其他任何东西. .关键是这是一个需要权限的操作,它返回一些值,并且在整个应用程序中使用.

This is a simplified example, so don't get on my case about blocking the UI, handling exceptions properly, etc. If you don't like file saving, you could imagine a getContact() or getPhoneState() or whatever. The point is it's a permission-needing operation that returns some value(s) and it's used throughout the app.

在Android< = Lollipop中,如果用户已安装并同意授予android.permission.WRITE_EXTERNAL_STORAGE或其他任何授权,那么一切都会很好.

In Android <= Lollipop, if the user had installed and agreed to granting android.permission.WRITE_EXTERNAL_STORAGE or whatever, all would be good.

但是在新的棉花糖(API 23)运行时权限模型中,您可以保存之前将该文件存储到外部存储中,您应该(1)检查是否已授予许可. 如果不是,则可能是(2)系统认为这是个好主意),举杯敬酒或其他任何东西,然后(3)要求用户通过对话框授予权限,然后基本上坐下来等待回调.

But in the new Marshmallow (API 23) runtime permission model, before you can save the file to external storage, you're supposed to (1) check if the permission has been granted. If not, possibly (2) show a rationale for the request (if the system thinks it's a good idea) with a toast or whatever and (3) ask the user to grant permission via a dialog, then basically sit back and wait for a callback...

(这样您的应用就可以坐着,等待...)

(so your app sits around, waiting...)

(4)当用户最终响应对话框时,权限请求,它们实际上是最终(7)继续执行该操作.

(4) When the user finally responds to the dialog, the onRequestPermissionsResult() method fires off, and your code now (5) has to sift through WHICH permission request they are actually responding to, whether the user said yes or no (to my knowledge there's no way to handle "no" vs. "no and don't ask again"), (6) figure out what they were trying to accomplish in the first place that prompted the whole ask-for-permissions process, so that the program can finally (7) go ahead and do that thing.

要知道用户在步骤(6)中试图做什么,需要事先通过特殊的代码(权限请求响应"),在文档中被描述为

To know what the user was trying to do in step (6) involves having previously passed a special code (the "permissions request response") which is described in the docs as an identifier of the type of permission request (camera/contact/etc.) but seems to me more like a "specifically, what you were trying to do when you realized you'd need to ask for permissions" code, given that the same permission/group may be used for multiple purposes in your code, so you'd need to use this code to return execution to the appropriate place after getting the permission.

我可能完全误解了它应该如何工作-所以请让我知道我是否要离开-但是更大的一点是我真的不知道该怎么做考虑到由于异步等待用户响应"部分而执行上述所有w/saveFile()方法.我考虑过的想法很不可靠,而且肯定是错误的.

I could be totally misunderstanding how this is supposed to work-- so please let me know if I'm way off-- but the larger point is I'm really not sure how to even think about doing all of the above w/the saveFile() method described previously due to the asynchronous "wait for the user to respond" part. The ideas I've considered are pretty hacky and certainly wrong.

今天的 Android开发者播客暗示可能存在一种同步解决方案在拐角处,甚至还讨论了Android Studio中一种神奇的,一步式的alt输入类型的添加权限请求"工具.尽管如此,如何将运行时权限过程推到saveFile()之类的东西中-我在想一些类似的事情:

Today's Android Developer Podcast hinted that there may be a synchronous solution around the corner, and there was even talk about a magic, one-step alt-enter type of "add a permissions request" tool in Android Studio. Still, how the runtime permission process might be shoved into a saveFile() or whatever-- I'm thinking something along the lines of :

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()也会失败,并且拒绝授予权限.也许可以使用checkPermission()周围的循环尝试最多询问3次或更多,或者更好的方法是该方法是否处理了理智的不烦人"政策.

So the above checkPermission() would fail if the user didn't have and also refused to grant the permission. Maybe one could use a loop around checkPermission() to try asking up to 3 times or something, or better would be if a sane dont-be-annoying-policy was handled by the method.

这样的事情可能吗?好吗这样的解决方案会阻塞UI线程吗?从播客中听起来,谷歌也许即将推出类似的解决方案,但我想思考一下是否存在某种东西-便利班,一种模式或某种东西-并不需要每个人都重构所有需要权限的操作,我必须假设这些操作会变得非常混乱.

Is such a thing possible? Desirable? Would any such solution block the UI thread? From the podcast it sounded like Google may have a solution like this coming 'round the corner, but I wanted to get thoughts on whether there was something-- a convenience class, a pattern, something-- that doesn't involve everyone having to refactor all permission-requiring operations, which I must assume could get pretty messy.

很抱歉,这个冗长的问题,但我想尽可能完整.我将立即取消答案.谢谢!

Sorry for the long-winded question, but I wanted to be as complete as possible. I'll take my answer off the air. Thanks!

更新 :这是上述播客的笔录.

Update: Here is the transcript from the podcast mentioned above.

收听大约 41:20 .在此讨论中:

Listen at about 41:20. In this discussion:

成绩单:

Tor Norbye(工具小组):"因此,对于开发人员来说似乎不应该做很多工作.但是我了解部分问题是这些不是同步调用,对吗?您必须要做的事情-实际上会更改您的活动编写方式以使其具有回调-因此,它确实有点像状态机,在此状态下,您... "

Tor Norbye (Tools team): "So it doesn't seem like it should be a lot of work for developers. But I understand part of the problem is that these are not synchronous calls, right?. So what you have to- actually change the way your activity is written to have a callback-- so it's really kinda like a state machine where... for this state, you-"

Poiesz(产品经理):"啊,我想-可能有一个-同步响应选项-"

Poiesz (product manager): "Ah- I thought- there was a- there might be an option for synchronous response--"

Norbye:"哦,那会变成东西的-"

Norbye: "Oh. that would make things--"

Poiesz:"我可以在内部与其他人交谈.我回想起有关同步的讨论,但我们可以找到答案."

Poiesz: "I can talk with folks internally. I recall a discussion about synchronous- but we can find out."

Norbye:"是的,实际上我们应该将其纳入工具中.在这里,您可以轻松地进行重构... "

Norbye: "Yeah. In fact we should probably make it into the tools. Where you have an easy refactoring..."

然后,他讨论了在工具中使用批注来确定哪些API需要权限..(到目前为止,哪种API不能满足IMO的要求),以及他如何希望有一天该工具能够在找到所需的代码后实际生成所需的代码.未经检查的危险"方法调用:

Then he talks about using annotations in the tools to determine which APIs require permissions.. (which as of now doesn't work that great IMO) and how he wants the tools someday to actually generate the required code if it finds an unchecked "dangerous" method call:

Norbye:" ...然后,如果您也使用M,它会说:'嘿,您实际上是在检查此权限还是在捕获安全异常?",如果您在不是,我们会说您可能需要在这里做一些事情来请求许可."我想要的是对此有个快速解决办法,在这里您可以进行"CHING!"并且它插入了所有合适的内容来进行询问,但是当我回头看时,这需要重新构造很多东西-添加接口和回调,并更改流程,而我们做不到. "

推荐答案

从棉花糖开始,我的理解是你做不到.

As of Marshmallow, my understanding is that you can't.

我必须在我的应用程序中解决相同的问题.这是我的操作方式:

I had to solve the same issue in my app. Here's how I did it:

  1. 重构:将依赖某种权限的每段代码移入自己的方法中.
  2. 更多重构:确定每种方法的触发条件(例如启动活动,点击控件等),如果方法具有相同的触发条件,则将它们组合在一起. (如果两种方法最终具有相同的触发器并且需要相同的权限集,请考虑合并它们.)
  3. 甚至更多的重构:找出依赖于之前调用的新方法的内容,并确保在调用这些方法的时间上具有灵活性:要么将其移入方法本身,要么移至至少要确保,如果以前没有调用过您的方法,那么您所做的任何操作都不会引发异常,并且一旦调用该方法,它就会按预期方式开始工作.
  4. 请求代码:对于这些方法(或其组)中的每一种,都定义一个整数常量以用作请求代码.
  5. 检查并询问权限:将这些方法/方法组中的每一个包装到以下代码中:
  1. Refactoring: Move every chunk of code that depends on permissions of some kind into a method of its own.
  2. More refactoring: Identify the trigger for each method (such as starting an activity, tapping a control etc.) and group methods together if they have the same trigger. (If two methods end up having the same trigger AND requiring the same set of permissions, consider merging them.)
  3. Even more refactoring: Find out what depends on the new methods having been called before, and make sure it is flexible about when these methods are called: Either move it into the method itself, or at least make sure that whatever you do doesn't throw exceptions if your method hasn't been called before, and that it starts behaving as expected as soon as the method is called.
  4. Request codes: For each of these methods (or groups thereof), define an integer constant to be used as a request code.
  5. Checking and asking for permissions: Wrap each of these methods/groups of methods into the following code:

.

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

  1. 处理响应:在每个要求许可的Activity中为onRequestPermissionsResult()编写一个实现.检查是否已授予请求的权限,然后使用请求代码来确定需要调用哪种方法.
  1. Handling responses: Write an implementation for onRequestPermissionsResult() in every Activity that asks for permissions. Check if the requested permissions were granted, and use the request code to determine what method needs to be called.

请注意,API需要Activity才能发出运行时权限请求.如果您具有非交互组件(例如Service),请查看此处是我如何在应用程序中解决此问题.

Be aware that the API requires an Activity for runtime permission requests. If you have non-interactive components (such as a Service), take a look at How to request permissions from a service in Android Marshmallow for advice on how to tackle this. Basically, the easiest way is to display a notification which will then bring up an Activity which does nothing but present the runtime permissions dialog. Here is how I tackled this in my app.

这篇关于您可以在Android Marshmallow(API 23)的运行时权限模型中同步请求权限吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆