用户个人隐私泄漏问题泛滥,引发用户与企业间的信任危机,个人隐私保护因此得到前所未有的重视。在移动应用开发领域,如果企业的应用程序未采用动态权限方式获取用户的隐私权限,将无法上架Google Play及国内的各大应用市场。对于一款标准的移动端商业app,动态权限功能已经成为必不可少的标配功能。
本文主要介绍如何使用YonBuilder移动开发技术,实现移动端的动态权限功能。
API介绍
YonBuilder 移动开发平台统一了Android和iOS两个平台的动态权限操作,提供了两个API函数来支持动态权限的开发:
hasPermission:用来判断应用是否已获取了某个(或某几个)应用权限的用户授权。
requestPermission:使用交互弹窗的方式,来向用户申请相关的应用权限。
更多API对象介绍,可访问https://docs.apicloud.com/Client-API/api查看。
实现思路
首先使用hasPermission检测权限,获取检测结果后,对权限检查结果进行判断。对于没有获取到的权限,再调用requestPermission函数进行动态申请。
**注意(可选操作):**当判断应用未获取某些权限并准备向用户发起动态权限申请前,可以加入一些增强产品体验的优化操作。
例如,使用代码设计实现一个美观的交互弹窗,向用户说明应用为什么要获取这些动态权限,以及如果无法获取相应权限将导致应用的某些功能无法使用的结果说明,让用户理解动态权限授权的必要性和合理性。
实现流程
1. 设置targetSdkVersion版本值
打开项res文件夹下的manifest.xml文件,查看其中的targetSdkVersion值是否≥26,如果不是则进行修改。
在当前的版本中,新创建的项目已自动创建manifest.xml文件,并设置targetSdkVersion默认值为30(见下面截图)。
如果是旧项目,则没有该文件,则可以使用新建文件的方式自行创建。
PS: 设置targetSdkVersion版本值≥26的原因
在Android上使用动态权限,要求app编译的目标SDK(即targetSdkVersion)为23及以上(对应为Android 6.0及以上系统),22及以下系统会执行缺省处理(手机厂商也可能定制处理),YonBuilder移动开发平台为满足更普遍的开发需求,在平台编译时,默认配置targetSdkVersion为22,即权限走系统缺省处理。
自2018年11月开始,Google Play以及国内大部分应用市场要求app编译目标SDK必须为26及以上,否则不予提交审核,所以需要在项目中设置声明。
2. 动态权限代码编写
关于动态权限申请和检测的时机,可以在app启动之后进行集中检测申请,也可以在不同页面下,在涉及相关隐私的逻辑中进行检测申请。
2.1 动态权限检测
// 定义需要动态申请的权限组数变量const permissonList = ['photos', 'microphone', 'camera', 'notification'];// 使用hasPermission函数判断当前应用已获取权限的授权结果const resultList = api.hasPermission({list: permissonList});
2.2 处理检测结果数据
// 定义缓存未授权权限的数组变量const tNeed = [];// 遍历处理检测结果数据,将未授权的权限重新push到一个新数组for (let i = 0; i < resultList.length; i++) {const element = resultList[i];if (!element.granted) {tNeed.push(permissonList[i]);}}// 结果判断if (tNeed.length === 0) {// 说明当前权限已获得授权,则当前动态权限校验已完成,调用后续的正常的业务逻辑代码即可。nextToDo(); // 调用后续的业务函数,这里仅做示例} else {// 这里编写对于未授权的权限的后续处理逻辑/*** [可选]这里可以加入一些产品优化方面的代码逻辑,例如* 可以弹出一个弹窗,向用户说明授予相关权限的必要性,当* 用户点击弹出的同意按钮后,再调用下面的api.requestPermission函数*/// 执行动态权限申请的相关业务逻辑(详见2.3)requestPermission(tNeed);}
2.3 动态权限申请
function requestPermission(perList){api.requestPermission({list: perList}, function(ret) {// 对判断结果进行判断处理handlePermissionResult(ret)});}
2.4 对动态申请结果的处理逻辑
api.requestPermission的函数回调参数(见下图):
对于api.requestPermission的回调结果,需要针对授权和未授权两种结果进行判断。
已授权则走正常的后续业务逻辑;对于未获得用户授权的结果,需要开发者根据产品业务逻辑编写相应的业务处理逻辑,例如直接退出app、退出当前页面、再次弹出提示弹窗等。
handlePermissionResult(resData, sucCB) {const [list = [], never] = resData;// 遍历申请结果数组const badPermissions = [];list.forEach(permission => {if(!permission.granted) {// 动态权限未获得授权badPermissions.push(permission);}});if(badPermissions.length === 0) {// 说明申请权限都已获得授权,则返回执行正常的后续业务逻辑if(typeof sucCB === 'function') sucCB();} else {// 这里需要结合具体的业务逻辑,编写对于未授权权限的处理逻辑。api.closeWidget({ silent: true }); // 示例代码,不授权将退出应用}}
2.5 注意事项
2.5.1当程序进行动态权限申请,而用户选择了不再提示(即返回结果never = true)时,后续程序再次调用api.requestPermission进行动态权限申请时,应用程序会自动跳转到手机系统的设置页面,不会再弹出申请权限的弹窗提示。
2.5.2如果某个权限涉及到程序的业务逻辑闭环,最佳实践方法是在每次该业务逻辑执行前,均进行该权限的校验处理,而不是仅校验一次。因为在程序运行中,用户是有可能切出到应用外,直接在手机设置里取消对应用的相关授权,这时应用程序内无法捕获相关事件,从而绕过检测机制,导致程序出现异常错误。
2.5.3所有应用程序中用到的隐私权限,都需要在程序编译打包的设置页面,进行相关权限勾选声明,否则程序运行时会出现各种异常错误。
总结
本文仅介绍了动态权限的判断和处理的简单基本逻辑编写,在实际的应用开发中,开发者需要结合具体业务逻辑场景灵活编写业务逻辑代码。
对于一些不重要的权限,可以在app启动后集中做一次判断处理,对于会影响后续业务流程的重要权限,需要在每一次逻辑代码执行之前,都进行一次权限校验,从而避免程序产生漏洞,发生异常错误。
另外对于未获取用户授权的相关权限处理,开发者可以和产品方面沟通,结合产品业务逻辑,综合考虑后续的处理逻辑。