一、申请权限的一般步骤
- 判断是否有权限,如果有权限,直接进行下一步。
- 如果没有权限,则开始申请权限。
- 如果用户授权,进行下一步。
- 如果用户拒绝授权,后面再次申请权限,系统为了不打扰用户,将不会出现系统的权限弹窗。在用户拒绝授权后,需要弹窗提示用户必须授权才能访问当前功能,并引导用户到系统设置中打开相应的权限。
每次申请权限的时候,都需要经过以上几个步骤,当申请的权限越来越多,大量的重复代码就出现了。为了减少重复代码,我封装了一个权限请求框架。
二、权限请求框架
桃夭是鸿蒙系统上的一款权限请求框架,封装了权限请求逻辑,采用链式调用的方式请求权限,极大的简化了权限请求的代码,同时支持在UI、UIAbility、UIExtensionAbility里面申请权限。需要注意的是,应用在UIExtensionAbility申请授权时,需要在onWindowStageCreate函数执行结束后或在onWindowStageCreate函数回调中申请权限。
本项目基于开源鸿蒙4.1开发,最低兼容到API 11,请将DevEco Studio升级到最新版,DevEco Studio版本低于5.0.3.403可能无法编译。
三、桃夭名称来源
桃夭一词出自古代第一部诗歌总集《诗经》中《诗经·桃夭》,“桃之夭夭,灼灼其华。”桃花怒放千万朵,色彩鲜艳红似火。
四、桃夭的使用方式
下载
申请权限
申请权限变得如此之简单。
五、实现原理
1.如何支持在UI、UIAbility、UIExtensionAbility里面申请权限。
可以使用联合类型,也可以使用重载。这里通过重载的方式来实现在UI、UIAbility、UIExtensionAbility里面申请权限。
UI、UIAbility、UIExtensionAbility里面最重要就是Context对象,申请权限的时候需要传入Context对象,我们需要从UI、UIAbility、UIExtensionAbility里面获取Context对象。这里采用策略模式。创建接口Origin,Origin代表从哪申请权限,定义getContext方法,由子类实现该方法。
ContextOrigin代表在在UI中申请权限,实现Origin接口,重写getContext方法。
UIAbilityOrigin代表在在UIAbility中申请权限,同样实现Origin接口,重写getContext方法。
UIExtensionAbilityOrigin代表在在UIExtensionAbility中申请权限,同样实现Origin接口,重写getContext方法。
2.检测申请的权限是否在module.json5文件中声明
申请的权限必须在module.json5文件中声明,否则桃夭会直接抛异常。如何检测申请的权限是否在配置文件中声明?如下代码,通过bundleManager对象获取应用信息,之后就可以获取应用在配置文件中声明的权限了。如果要申请的权限没有module.json5文件中声明,那就会抛异常。
3.检测其它配置
对于位置权限,有三种情况:
第一:申请模糊位置权限,大部分情况下,不会申请模糊位置权限,更多的是第二种情况。
第二:申请精确位置权限。
第三:申请后台位置权限。
针对位置权限,我们需要额外的配置下。
如果用户申请精确位置权限,那就要先申请粗略位置权限。
如果用户申请后台位置权限,那就先申请模糊位置权限和精确位置权限。当同意这两个权限后,弹窗提示用户到系统设置中打开相应的权限,用户在设置界面中的选择“始终允许”应用访问位置信息权限,应用就获取了后台位置权限。
4.判断是否有权限
当所有的检测都通过后,就可以判断是否有权限了。调用checkAccessToken()方法来校验当前是否已经授权。如果已经授权,则回调告知调用者已经有权限,否则需要进行下一步操作,即向用户申请授权。
5.申请权限
调用requestPermissionsFromUser(),如果用户授权,则调用mOnGranted。如果用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限。
6.系统设置弹窗
用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限。但在跳转系统设置之前,需要弹窗提示用户,这里提供一个默认的弹窗。如果这个弹窗不满足你的要求,你可以改掉。当用户在弹窗里面点击取消,则隐藏弹窗。当用户在弹窗里面点击去设置,则跳转到系统设置页面。
7.跳转到设置页面
使用下面的代码即可跳转到系统设置页面。构建一个want对象,指定bundleName 、abilityName 、uri 、parameters 等参数,调用startAbility 。
目前只有华为手机使用了开源鸿蒙系统,不排除后续会有其它的厂商使用开源鸿蒙系统,到时want对象的bundleName、abilityName、uri可能会不一样。在这种情况下,上面的代码就会有兼容性问题。这就需要针对不同的品牌,创建不同的want对象。这里采用策略模式。如下代码,创建SettingWant接口,定义getWant方法,由子类实现该方法,也就是由子类来创建want对象。
新建DefaultSettingWant类,DefaultSettingWant是一个默认创建Want对象的子类。
对于华为手机,我们就继承DefaultSettingWant,直接使用默认创建的Want对象。
如下代码,先创建SettingWant 对象,通过deviceInfo.brand判断品牌,如果是华为手机,则创建HuaWeiSettingWant 。调用getWant获取到Want对象,调用startAbility跳转到系统设置。
六、源码
更多具体的代码,请下载源码或者查看OpenHarmony三方库中心仓。