Android运行时权限api“requestPermission()”设计

时间:2016-05-11 09:26:46

标签: android api android-permissions

正如Android去年在Android API 23及更高版本中添加的运行时权限,我有一个查询

ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

并且

   ActivityCompat.requestPermissions(new String[]Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

api用于请求权限。在上面的库中,我们必须提供应该已经实现ActivityCompat.OnRequestPermissionsResultCallback接口的Activity实例。支持版本的片段和AppcompatActivity,FragmentActivity默认实现了这一点。

为什么我们只需要以Activity或Fragment的形式提供回调引用?我们可以将此API设计为

ActivityCompat.requestPermissions(context,
                    new String[]{Manifest.permission.READ_CONTACTS},
                    MY_PERMISSIONS_REQUEST_READ_CONTACTS,ActivityCompat.OnRequestPermissionsResultCallback callback);

我的意思是我们必须提供片段的活动或支持版本。如果我们想要检查任何其他简单类的外部活动怎么办?我只有一个GeofenceManager类需要Location权限,而且许多Activity或类需要来自GeofenceManager单例类的一些信息。

我是否必须在每项活动中实施OnRequestPermissionsResultCallback?我认为如果Api在上面的建议设计中会好得多。以这种方式设计API必须有一些重要原因。我的小经验无法得到它。

2 个答案:

答案 0 :(得分:2)

所有AppCompat API都应尽可能轻松地替换为其原生版本。

表示API 23实现上的原生android.app.Activitypublic final void requestPermissions方法和public void onRequestPermissionsResult回调。

那么这些如何被转换为AppCompat。将它们作为独立的实体肯定会导致更灵活的方法,但它也会导致将来无法在设备更新时弃用AppCompat。

你可以争论为什么API23活动不会做同样的事情,但这只是一般的Android总是如何以及他们对待一切的方法,例如onActivityResult

此外,必须将这些内容附加到活动中,因为只有当它处于前台时才应该请求权限。

修改

进一步思考,还有另一个原因。回转! 随着活动在轮换期间被销毁和重建,基于interface的回调可能非常棘手。

回调方法需要某种类型的上下文或进行进一步操作(转到下一个活动,或从新授予的权限加载/读取内容)。因此,如果编码器将接口作为匿名内部类传递,或者使其活动扩展该接口并发生旋转,则会泄漏活动。或者回调方法需要接收上下文参数,但是框架必须跟踪哪个活动是当前上下文发送回回调。所有这些都会非常快速地变得非常复杂。因此,一种简单直接的方法就是将其作为活动的实际方法。

答案 1 :(得分:0)

我知道回答我自己的问题有点晚了,但我仍然认为我的回答会对这个问题有所帮助。

在Android中,有5种类型的流程,基于优先级。这些是前台进程,然后是任何可见进程,服务进程,后台进程,最后是“空”进程。

前台进程具有最高优先级,因为在大多数情况下,用户直接使用这些进程的组件,如活动或前台服务。但我们的案子属于第二种程序。一个可见的过程。

注意 :权限对话框未显示在请求权限的活动中。事实上,这是一个活动!

在某些情况下,您的活动可见但不在前台。一个简单的例子是前台活动以Dialog主题或半透明活动开始新活动。 但请记住,仅仅因为你是可见的并不意味着你不能被杀死。如果前台进程有足够的内存压力,您的可见进程仍有可能被终止。从用户的角度来看,这意味着当前活动背后的可见活动被替换为黑屏。当然,如果您正确地重新创建了您的活动,那么只要关闭前台活动而没有任何数据丢失,您的流程和活动就会恢复。

即使可见,您的活动和进程也可能被杀死,这是startActivityForResult()+onActivityResult()requestPermissions()+onRequestPermissionsResult()流不带回调类实例的原因之一 - 如果您的整个进程已经死亡,那么做每个回调类实例。如果您看到使用回调方法的库,请意识到它对低内存压力情况不具备弹性。

注意:Android只会杀死进程,而不会杀死组件。永远记住这一点。

这是为什么Android中的requestPermission()API按原样设计的主要原因之一,而不是我提到的问题。