本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每个工作日都有文章更新。
PermissionX这个开源项目起源于我今年出版的新书《第一行代码 第3版》,本来的主要目的只是为了带领读者朋友们学习如何开发并发布一个开源库。然而随着我发现这个项目不仅有学习的价值,还可以真正投入到实际项目的使用当中,于是后面又对PermissionX进行了多个版本的迭代,目前已经成为了一个非常稳定和方便的权限请求库。
在1.3.0版本当中,PermissionX支持了自定义权限提醒对话框的功能,解决了长期以来被大家吐槽的对话框界面过丑的问题。现在大家可以自由发挥,定制出任意符合你们项目UI风格的对话框。具体过程可以参考这篇文章 PermissionX重磅更新,支持自定义权限提醒对话框 。
今天很高兴地告诉大家,PermissionX又推出了最新的1.4.0版本,这次的更新将会让整个权限请求的流程拥有更棒的用户体验。而更棒的用户体验通常又会带来更高的权限请求通过率,所以这是相当重要的一次版本更新。
那么接下来我们就看一看PermissionX 1.4.0到底带来了哪些新东西吧。
支持DialogFragment
刚才已经提到了,在上一个版本当中,PermissionX引入了自定义权限提醒对话框的功能,使得开发者可以自由地定制你想要的对话框样式。比如我在上篇文章中给出了如下的效果图示例:
这种权限提醒对话框是基于Dialog类来进行实现的,开发者在自定义对话框的时候需要继承PermissionX提供的RationaleDialog,并对必要的几个方法进行实现。
我个人认为这种实现方案是没有问题的,PermissionX控制整个权限的请求流程,而开发者可以自由控制UI的展示,非常完美。
然而,有朋友在GitHub上对这种方案提出了疑问,因为他想要使用DialogFragment来自定义权限提醒对话框,PermissionX的限制导致他只能使用Dialog了。
DialogFragment也是Google推荐使用的一种对话框实现方案,虽然我认为DialogFragment能实现的功能用Dialog也都能实现,但是强制使用Dialog确实显得有那么一些不友好。
于是我就开始思索着要不要完全重写自定义对话框这部分的实现,不再强制要求使用某一种固定的实现方式,而是只提供接口标准,具体怎么实现完全由开发者自己控制。
相信我,我确实这样做了。当时我的想法是,PermissionX只定义显示对话框,关闭对话框等必要的接口,至于实现方面不做任何限制,你可以用Dialog,也可以用DialogFragment,甚至可以用PopupWindow,或者是完全自定义的控件都行。
然而真正用了这种方案之后,我发现这并不是一个好的选择。因为PermissionX本来是内部自己控制着整个权限请求流程的,开发者完全不需要关心内部的逻辑,只需要自定义界面就行了。但是放开对话框的实现方式之后,开发者需要对自己实现的对话框负责,你需要考虑用户点击确定按钮后重新请求权限,需要考虑用户点击取消按钮后回调请求结果,需要考虑对话框取消的时候如何防止权限请求事件丢失,需要考虑横竖屏旋转时怎样防止window leak等等一大堆问题。
我不禁思考,这样的PermissionX真的还算好用吗?
所以,最终我把编写的这些代码全部Rollback,否定掉了这个方案,因为我不想为了这种不知何时才能用得到的灵活性,去给开发者增加额外的负担。
虽然上述方案是否定了,但是对于DialogFragment的需求却是实实在在存在的。所以最终我采取了和之前一样的方式,增加了一个RationaleDialogFragment的类,该类是继承自DialogFragment的,里面也定义了PermissionX所要求的几个必要的方法,开发者在使用DialogFragment自定义对话框时同样将这几个必要的方法进行实现即可。整体实现过程和1.3.0版本是一模一样的。
虽然看上去这种方案略微有点笨拙,但是请相信我,这可能是最好的方法了。不然你的PermissionX会变得非常不稳定,比如频繁在崩溃和权限事件丢失之中挣扎。
关于对DialogFragment的支持就到这里。但,这不是本文的重点。
最棒的用户体验
为什么那么多人想要自定义权限提醒对话框?因为PermissionX默认的权限提醒对话框实在是太丑了。
例如我们调用如下代码来申请权限:
PermissionX.init(this)
.permissions(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO)
.onExplainRequestReason {
scope, deniedList ->
val message = "PermissionX需要您同意以下权限才能正常使用"
scope.showRequestReasonDialog(deniedList, message, "确定", "取消")
}
.request {
allGranted, grantedList, deniedList ->
if (allGranted) {
Toast.makeText(activity, "所有申请的权限都已通过", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(activity, "您拒绝了如下权限:$deniedList", Toast.LENGTH_SHORT).show()
}
}
在请求的权限被用户拒绝时,PermissionX将会弹出下图所示的权限提醒对话框。
这种对话框在我们的测试程序中用用还可以,在线上项目中使用肯定是不行的,因为用户体验不够友好。
那么为了能让权限提醒对话框变得更加好看,PermissionX在1.3.0版本中引入了自定义对话框样式的功能,并且当时我还给大家演示了一种自定义对话框的实现过程,最终的对话框效果图如下:
可以看到,使用了自定义对话框的方式之后,我们可以自由地控制界面上的元素和内容,用户体验也得到了明显的改善。
不过,即使这样,还是有朋友在评论区里留言,嫌这个对话框太丑了(1人嫌丑,42人点赞)。
不过这个丑我是不背锅的,我只是为了演示自定义对话框的实现过程而已,具体对话框的丑和美还是掌握在你自己手里的。
那么看上去该支持的功能都已经支持了,PermissionX 1.4.0版本里又优化了什么内容呢?
最重要的一点就是,1.4.0版本中我对默认的权限提醒对话框进行了大幅的优化。
看上去好像并不是什么重磅功能,但恰恰相反,优化默认权限提醒对话框相当重要,这大大提升了PermissionX的用户体验,同时大大降低了PermissionX的使用成本,因为自定义对话框总体来说还是比较麻烦的。
现在,只要你升级了1.4.0版本,使用和上面完全相同的代码进行权限请求,你将会得到完全不同的权限提醒对话框界面,效果如下图所示:
可以看到,现在的对话框在用户体验方面无疑是完胜了之前的对话框,用户看到这样的界面也会更加赏心悦目。
那么PermissionX是如何做到的呢?
首先PermissionX会根据开发者在showRequestReasonDialog()方法中传入的deniedList来获取这些权限分别属于哪些权限组。因为在界面上其实并不需要将deniedList中的权限全部显示出来,而是只显示要申请的权限组名即可,这样可以让界面更精简。
需要注意的是,在Android 9及以下系统,我们可以通过系统API来自动获取某个权限属于哪个权限组,代码如下所示:
context.packageManager.getPermissionInfo(permission, 0).group
从Android 10开始Google禁用了这个功能,所以在之后的版本中需要手动设置每个运行时权限对应了什么权限组。这个工作是相当繁琐的,但是好在PermissionX在内部已经处理了这个功能。
另外,为了让界面元素更加丰富,我们在每个权限组名的前面还加上了该组所对应的图标,图标的获取可以通过如下代码实现:
context.packageManager.getPermissionGroupInfo(permissionGroup, 0).icon
如此一来,一个内容丰富,赏心悦目的权限提醒对话框也就诞生了。
然而,PermissionX做到的还远不止这些。我们都知道,从Android 10系统开始,Google引用了深色主题功能,一个出色的App在用户开启了深色主题模式之后,应该自动将界面也切换成深色模式。
而PermissionX同样对此功能进行了适配,在手机启用了深色主题模式之后,权限提醒对话框的效果如下图所示:
对话框上的颜色都是我精心调整过的,不管是深色主题还是浅色主题,看起来都会非常舒适。
除此之外,如果你的App要做海外版本,PermissionX也进行了原生的支持。你只需要保证传递给PermissionX的文字内容都是经过翻译的即可,其他部分PermissionX会根据当前手机系统的语言进行展示。
比如我们将手机系统的语言切换成英文,然后使用如下代码进行权限请求:
PermissionX.init(this)
.permissions(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO)
.onExplainRequestReason {
scope, deniedList ->
val message = "PermissionX needs following permissions to continue"
scope.showRequestReasonDialog(deniedList, message, "Allow", "Deny")
}
.request {
allGranted, grantedList, deniedList ->
...
}
最终权限提醒对话框的效果如下图所示:
再来看一张日文版的效果图:
到这里为止,PermissionX基本就做到了面向开发者提供最简单的API接口,面向用户提供最棒的用户体验这样的双层标准。
另外我们还可以通过串接一个explainReasonBeforeRequest()方法,让权限提醒对话框在开始请求权限之前显示,这样就能实现先解释申请原因,再执行请求权限的功能。通常这样的权限请求方式对于用户来说更加友好,用户同意授权的概率也会更高。
PermissionX.init(this)
.permissions(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO)
.explainReasonBeforeRequest()
...
最后我们通过一个动画来完整体验一遍整个权限请求的流程吧。
自定义TintColor
虽说默认权限提醒对话框上面使用的颜色都是我精心调整过的,但是可能却未必适合你们的项目。因为每个项目都会有自己的主题色,设置一个与项目主题相符的颜色或许比使用默认的颜色更加合适一些。
目前,默认的权限提醒对话框上,权限组图标、确定、取消按钮,使用的都是蓝色。而如果你觉得这种颜色和你们项目主题风格不搭的话,也可以设置成任意你想要的颜色。
设置的方式非常简单,就是在PermissionX的请求链上再串接一个setDialogTintColor()方法即可,如下所示:
PermissionX.init(this)
.permissions(Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.RECORD_AUDIO)
.setDialogTintColor(Color.parseColor("#008577"), Color.parseColor("#83e8dd"))
...
这里setDialogTintColor()方法接收两个参数,其中第一个参数是设置浅色主题下的颜色值,第二个参数是设置深色主题下的颜色值。既然是要自定义颜色值,那么肯定要把浅色主题和深色主题两种场景都考虑到才行。
现在重新运行程序之后,浅色主题和深色主题下的对话框效果分别如下图所示:
可以看到,对话框上的权限组图标、确定、取消按钮的颜色都得到了修改,使用这种方式就可以让PermissionX更好地贴合你们项目的主题风格了。
如何升级
关于PermissionX新版本的内容变化就介绍到这里,升级的方式非常简单,修改一下dependencies当中的版本号即可:
dependencies {
...
implementation 'com.permissionx.guolindev:permissionx:1.4.0'
}
另外,如果你的项目还没有升级到AndroidX,那么可以使用Permission-Support这个版本,用法都是一模一样的,只是dependencies中的依赖声明需要改成:
dependencies {
...
implementation 'com.permissionx.guolindev:permission-support:1.4.0'
}
PermissionX的项目主页地址是:
https://github.com/guolindev/PermissionX
另外,本篇文章主要介绍的是PermissionX 1.4.0版本的新特性。如果你之前并没有接触过PermissionX,可以通过我编写的《PermissionX权限系列专栏》逐步进行学习,里面有非常详尽的用法讲解。
如果想要学习Kotlin和最新的Android知识,可以参考我的新书 《第一行代码 第3版》,点击此处查看详情。
关注我的技术公众号,每天都有优质技术文章推送。
微信扫一扫下方二维码即可关注:
转载:https://blog.csdn.net/sinyu890807/article/details/108432486