【木棉花】向用户动态申请授权 原创 精华
前言
应用向用户动态申请授权,是指在用户使用应用的过程中,应用方会根据应用场景和业务向用户动态地请求相应的权限。例如,当应用需要访问用户的相机或麦克风时,会向用户弹出一个授权请求框,询问用户是否允许应用访问这些设备,而用户可以选择允许或拒绝此次授权请求。这种方式可以提高应用的安全性,在一定程度上保护用户的隐私信息安全。
Nothing theoretical can be clearer than the code. 本期笔者将以一个Demo为例,与读者们共同探讨在ArkUI的框架中如何实现动态申请授权的功能
正文
通常情况下,一些提供基础功能的权限可以通过静态的方式获取(即直接将开发者需要的权限在模块级别的module.json5文件中声明),如联网权限。而对于一些能够为应用提供用户的隐私数据的敏感权限,则需要以动态的方式可视化地向用户申请。本期的Demo以申请获取大致位置权限(即"ohos.permission.APPROXIMATELY_LOCATION")为例,实现动态申请权限的功能。
新建工程
打开DevEco Studio(开发工具的版本必须支持API9),创建一个新的project,相关勾选如下
在module.json5中添加相应的权限
成功创建工程后,在工程文件目录中打开目录:entry/src/main/module.json5, 添加两个权限——定位权限( "ohos.permission.LOCATION")和获取大致位置的权限("ohos.permission.APPROXIMATELY_LOCATION" )。
事实上,当应用同时获取以上两种权限后,应用可以获取设备的精准位置,精准度在米级别。
集成功能模块
要实现向用户动态申请授权的功能,我们需要制作两个功能模块,分别是检查是否已获得所需权限的功能和向用户发起权限申请的功能。为了达到公共调用和功能模块化,我们需要将这两个功能模块集成到两个不同的TypeScript文件中,并将可调用接口导出
在ets文件夹下新建目录,并将其命名为Service
在Service目录下新建两个TypeScript文件(右键Service目录,选择新建,再选择TypeScript),分别命名为Detector与Applicant
在编辑器中打开Detector.ts,加入以下代码以集成检查应用是否已获得所需权限的功能,各代码块的具体功能已写注解
因为笔者已给代码添加了注释,所以笔者就不对这个模块做太多啰嗦的分析了。这个模块的大致执行逻辑是,通过调用系统能力@ohos.bundle.bundleManager获取本包的accessTokenId,再调用系统能力@ohos.abilityAccessCtrl,在传入accessTokenId和权限列表的条件下检查module是否已获取权限列表中的每个权限。当atManager的异步方法checkAccessToken返回结果为0时,表示所需权限均已被提供。
在编辑器中打开Applicant.ts,加入以下代码以集成向用户发起权限申请的功能,各代码块的具体功能已写注解
这个模块的大致执行逻辑是,在atManager的异步方法requestPermissionsFromUser
中传入所需的上下文对象和待申请权限列表,并等待其异步过程的结束。在requestPermissionsFromUser的异步过程中,系统会弹出选择框,询问用户是否提供权限。当用户点击选择框中的允许或禁止时,权限会被授予或否,异步过程随即结束(此处指的是申请单个权限的场景),requestPermissionsFromUser将申请结果以number型数组的形式输出。当此数组中的每个元素的值都为0时,表示所有权限都成功获得,否则,用户拒绝授权了至少一个权限。
Detector.ts和Applicant.ts均默认导出了接口,想要在其他地方调用它们的功能,只需导入接口即可。
编辑页面UI
添加图片资源
在工程文件目录中打开目录:src/main/resources/rawfile, 添加两张任意的图片(可以在IDE中将待添加的图片资源直接粘贴至rawfile目录下,也可以在文件资源管理器中通过文件路径打开rawfile目录并添加图片资源),分别命名为image1和image2。当然,图片的格式没有要求,只要在之后的步骤中能被正确引用即可。
设计页面UI
打开Index.ets,删除原有的Text组件,新增两个Button组件和一个Image组件(相关属性设置如下),并声明一个用@state修饰的布尔变量ifAccessible
预览器效果如下:
添加自定义弹窗
首先,在组件Index之外用struct声明一个新的自定义组件dialog,并用装饰器@CustomDialog对其进行修饰,使dialog拥有成为自定义弹窗的能力。接着,我们对弹窗显示的内容进行自定义设置,在build函数中加入自定义UI声明。其中,CustomDialogController类型的成员变量controller和字符串类型成员变量message皆必不可少,后者可用于对dialog的外部传参。
之后,我们在组件Index中new两个弹窗控制器( CustomDialogController类的实例),并分别将它们赋予两个私有成员变量(dialogController_Accessible和dialogController_Inaccessible)以供调用。当然,我们是用两个message不同的dialog组件来构造这两个弹窗控制器的,所以弹窗控制器dialogController_Accessible和弹窗控制器dialogController_Inaccessible可用于打开和关闭它们所对应的dialog。
编写回调方法
首先,我们从先前步骤中已集成的功能模块Detector导入异步函数Check_Access,并自定义异步方法detect。在detect的方法体中,我们通过关键字await等待异步过程,这意味者原本的异步任务变成了一个等价的延时同步任务,保证了detect中操作语句的顺序执行。由于关键字await只能在异步方法或异步函数中出现,所以detect必须是异步方法。根据Check_Access的不同返回结果(成功或失败),系统会生成不同内容的弹窗与用户交互。detect()编写完后,我们在用于检查应用是否获得权限的Button组件的onclick事件中加入此异步方法。
接着,我们从先前步骤中已集成的功能模块Applicant中导入异步函数Request_Permission_From_Users,并导入common。随后,我们通过getContext方法获取上下文对象,并将其转化为UIAbilityContext类型,存入私有成员变量context中。之后,自定义异步方法apply,在方法体中将成员变量context传入异步函数Request_Permission_From_Users中。这样以后,我们便可在用于向用户动态申请权限的Button组件的onclick事件中加入自定义方法apply了。
至此,本期的Demo完成了。
真机&模拟机调试
Demo完成之后,我们需要用模拟器或真机来运行以查看效果。
事实上,变量ifAccessible的值应该保存在本地的数据库里,这样每次重新创建此Demo的页面实例时,才能正确地显示对应图像,读者们可以自行修复这个bug。
当然,我们也可以打开日志栏,通过日志信息观察功能模块的运行。打开编辑器下方的Hilog,勾选'show only js log',并在标签筛选栏中输入0FEFE,过滤后的日志信息如下。
结语
如果想了解更多有趣的技术分享,欢迎订阅我的新专栏《ArkTS Laboratory》。
文章所述仅代表个人理解,如有不足恳请读者不吝赐教。
其实挺好奇手机权限能分这么细,pc就没有
所以pc的安全问题也多
很好的文章。但是博主是不是把两个dialog里的信息写反了?
写的大大的好