引言
在实际项目开发中,有些场景需要获取用户设备的唯一标识去推动实现相关的业务逻辑需求。随着移动端(Android
和、iOS
)加强了对用户隐私信息的保护,在高版本的操作系统中,相关的获取规则已经方法了变化。本文主要讲解一下,在YonBuilder移动开发
技术体系中,如何去获取设备唯一标识信息。
概述
简单来说,在YonBuilder移动开发
技术体系中,可以通过引擎提供的 api.deviceId
函数方法去获取app运行时的设备唯一标识。
以下是官方文档关于api.deviceId
的说明: deviceToken说明文档跳转
从文档说明内容我们可以明确获取到以下的结论,即因为手机操作系统的限制,App
不同的手机系统上可能获取到的唯一标识信息是不同的。
-
在
iOS
上获取的是与证书相关联的uuid,其他的已经被系统限制了; -
在
android
上优先返回的是IMEI,如果无法正常获取,则按以下优先级顺序获取返回值:IMEI
>ANDROID_ID
>MAC
地址 > 设备序列号 > 随机UUID
小知识点:
-
IMEI
: 国际移动设备识别码,涉及访问用户隐私信息,因此需要遵循最新的安全和隐私政策。 -
ANDROID_ID
: 这是由Google
提供的一个64位的字符串,作为设备的唯一标识符。它在设备首次启动时生成,在重置设备(出厂设置恢复)之前保持不变。 -
Mac
地址:Media Access Control Address,是分配给设备网络接口的唯一标识符。
在android上获取IMEI的相关操作
之前有小伙伴反馈过自己开发的APP
,在早期版本是可以通过获取 api.deviceId
到IMEI信息的,不过最新编译的新版本中,已无法获取IMEI
,只能拿到序列号了,想知道这是怎么回事,如何处理。
其实导致这个问题的原因是,在android
上,从Android 6.0
(API level 23) 开始,获取 IMEI 需要申请 READ_PHONE_STATE
权限,并且从 Android 10
(API level 29) 开始,普通权限已经不足以获取 IMEI,应用还需要声明自己是设备或配置文件所有者,或者属于特定的系统组件。
也就是说现在APP
运行在高版本的android
系统上了,因为规则改变了,所以导致无法获取。想解决这个问题,需要我们声明一下READ_PHONE_STATE
权限,并在项目代码中加入相应的权限判断和请求逻辑,具体流程如下:
项目代码中添加动态权限判断和请求逻辑
可以使用官方引擎提供的 api.hasPermission
和 api.hasPermission
,去判断和申请动态权限。READ_PHONE_STATE
权限,在YonBuilder移动开发中,对应的是phone
、phone-r
权限,根据业务需求选择,如果仅仅是想获取IMEI,根据最低权限原则,建议使用 phone-r
该相关权限代码的嵌入逻辑,应该是在原本的调用 api.deviceId
命令的位置, 改为调用下面的封装函数去获取执行(因为函数内进行权限申请是方法是异步回调,所以该函数也被封装为异步回调方式)。当然,下面的函数方法仅仅是作为基础的功能示范代码,更丰富完善的逻辑,大家可根据自己的项目代码实际情况进行修改优化。
function handleGetDeviceId(callback) {
if (typeof callback !== 'function') {
console.warn('【警告】:回调函数参数不正确');
return;
}
// 判断当前系统及版本为android 6.0及以上,是否需要执行权限申请逻辑
if (api.systemType !== 'android' || parseInt(api.systemVersion) < 6) {
callback(api.deviceId);
return;
}
var permission = 'phone-r';
// 进行动态权限判断
var hasRes = api.hasPermission({
list: [permission]
});
if (hasRes[0].granted) {
// 当前应用已获取相关权限,返回设备ID
callback(api.deviceId);
return;
}
// 未获取权限,弹窗提示用户说明需要申请权限的意图(可以自行修改下面的弹窗方式,进行弹窗样式自定义,当前代码仅做示范)
api.confirm(
{
title: '提示',
msg: '需要获取设备ID,请允许应用获取电话权限'
},
function (ret, err) {
if (!ret || ret.buttonIndex !== 1) {
console.warn('用户拒绝了权限申请');
callback('');
return;
}
// 申请动态权限
api.requestPermission(
{
list: [permission]
},
function (res) {
if (ret && Array.isArray(res.list) && res.list[0].granted) {
callback(api.deviceId);
} else {
// 此处仅做示范,这里可以根据返回的res内容进行更复杂的逻辑判断,例如用户是否已永久拒绝等操作
console.warn('用户拒绝了权限申请');
callback('');
}
}
);
}
);
}
设置当前APP的SDK版本,以提高获取IMEI的成功率(可选操作)
从上面的描述可知,从Android 6.0
(API level 23) 之后开始需要动态权限获取IMEI,从 Android 10
( API level29
) 开始需要特殊权限才能获取到IMEI,所以如过实际场景允许,可以考虑设置APP的 API Level
为 28,这样可以更大概率的保证动态权限申请可以成功。(PS: 对于运行环境 ≥ API level 29
的,只能期望你的客户手机是找厂家特制的手机系统,这样可以和厂家沟通给你的app内置的应用权限,否则就别想了)
当前操作为可选操作,降低API
等级后,会导致部分使用了高版本系统API
的原生插件的部分命令失效或者运行报错,所以需要根据你的项目实际情况审慎考虑。设置API Level
,可以通过在项目根路径res
文件夹 内编译 manifest.xm
文件(没有的话,自己创建一个即可),具体编译后的 manifest.xm
内容如下
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<application name="targetSdkVersion" value="28"/>
</manifest>
勾选权限,编译版本
完成上面步骤的代码编译修改后,记得将最新代码同步到云端工作台(使用代码块上传方式) 或者 git
仓库(使用git
仓库方式)
更新同步代码后,在云端工作台的应用详情页切换到「移动打包」面板页, 需要先设置勾选本次功能需要的READ_PHONE_STATE
权限,见下图
如果是申请的 phone-r
, 则仅勾选 「获取手机信息」即可,如果使用了 phone
,则需要增加勾选 「电话」权限
PS: 应用新增的权限,需要同步的在你应用的隐私协议里进行该权限的使用和申请的理由说明,如果不做出相关说明,则应用上架有可能被拒。
完成权限配置后,我们就完成了新增动态权限去获取IMEI的全部过程,此时可以新的版本编译,进行安装测试了。
总结
上面我们介绍了关于使用引擎的 api.deviceId
去获取设备的唯一标识信息的相关背景描述和整个的开发流程。其实,现在目前有很多的第三方平台也在提供获取设备唯一标识的服务,如果他们提供有原生的SDK
,也可以通过YonBuilder移动开发
平台的插件封装技术讲该SDK
封装成插件去调用。插件开发需要具体原生语言的开发技术,这里就不展开描述了。
这里我要提供另一种思路,就是目前普遍在使用的 浏览器指纹技术
。
浏览器指纹技术(Browser Fingerprinting)是一种通过收集和分析用户浏览器及其环境的各种属性来唯一标识用户的机制。它不依赖于传统的 cookies
或其他形式的存储,而是利用了浏览器和设备的独特特性,如屏幕分辨率、时区、安装的语言、字体列表、插件、操作系统信息、浏览器版本等。
因为 YonBuilder移动开发
属于 混合APP
开发框架,它本身就有内置的浏览器引擎,所以天然就满足 浏览器指纹技术
的实现条件,比如 浏览器指纹技术
实现手段之一的 Canvas Fingerprinting
(通过 JavaScript
代码让浏览器绘制一个隐藏的图像,并根据生成图像的像素数据创建唯一的哈希值)。更详细的细节和实现,我们这边不再展开,这里在结尾处,给开发者伙伴们提供一种新的解题思路,有兴趣的小伙伴可以根据相关的关键词自行去互联网上进行深入的学习了解。