前言
1、IMEI 等设备标识符已经被认定为用户隐私的一部分,在非必要的场景获取甚至频繁获取 IMEI,会被认定为违规获取用户信息的行为;
2、 Android 10 开始,应用无法获取 IMEI、MAC 等设备唯一标识(申请 READ_PRIVILEGED_PHONE_STATE 权限后也可以获取,但这个权限只有系统应用能够获取)。如果应用强行获取,则会获取到 null 信息或发生 SecurityException(取决于 targetSdkVersion);
3、为了解决这个问题,国家相关部委成立了移动安全联盟 MSA,制定了一套《移动智能终端补充设备标识体系》。因为其中最重要的一个标识符是 OAID 匿名设备标识符,因此也有人把这个体系简称为 OAID。
关键词介绍
-
UUID 设备唯一标识符 是不依赖于这个体系的,它们在设备出厂时就固化到硬件信息上了,即使恢复出厂设置也不会重置;
-
OAID 匿名设备标识 是 UUID 的替代品,在终端首次启动时生成。同一设备的 OAID 相同,因此可以在多个应用之间共享,恢复出厂设置会重置 OAID;
-
VAID 开发者匿名设备标识符 是开发者维度的 ID,在应用安装时生成。同一设备上且同一开发者的所有应用 VAID 相同,其他情况 VAID 不同,重新安装应用会重置 VAID;
-
AAID 应用匿名设备标识符 是应用沙盘维度的 ID,在应用安装时生成。即使是同一设备且同一个开发者的应用,AAID 也不同,重新安装、清除用户数据会重置 AAID。
支持厂商
想要实现设备唯一,必须是由厂商支持,所以移动安全联盟的成员和专注于中国市场的厂商会率先支持(我使用的一加截止2020.5.6没有支持),华为、小米、OPPO、vivo、中兴、努比亚、魅族、联想、三星等设备厂商均将逐步支持(一些老的设备且没有经过系统更新的不支持)
OAID使用
走正常流程是根据 MSA 的要求,下载 SDK 和集成文档前需要注册一个企业账户,这一步按照指引提交相关信息和资料即可,一般 1~2 个工作日就可以审核通过。审核通过还得去商城申请APP的信息才能使用,下面说一种省去这些麻烦步骤,通过反射的方法 直接使用他们sdk生成唯一编号的方法,下面是代码。
如需获取sdk 关注公众号后 回复关键词 OAID 即可。
1、下载sdk之后配置到项目里
supplierconfig.json里只需给一个空结构就行,无需添加APP信息。
supplierconfig.json文件{ "supplier":{ "vivo":{ }, "xiaomi":{ }, "huawei":{ }, "oppo":{ } }}
2、调用代码
public static boolean getID(Context context) { try { Class<?> refCus = Class.forName("com.bun.miitmdid.core.MdidSdkHelper"); Class<?> callback; try { // 1.0.10 版本 callback = Class.forName("com.bun.miitmdid.core.IIdentifierListener"); } catch (ClassNotFoundException e) { // 1.0.23 版本 callback = Class.forName("com.bun.miitmdid.interfaces.IIdentifierListener"); } final InnerIdSupplier mh = new InnerIdSupplier(context); Object mObj = Proxy.newProxyInstance(context.getClassLoader(), new Class[]{callback}, mh); Method initSdk = refCus.getDeclaredMethod("InitSdk", Context.class, boolean.class, callback); int result = (int) initSdk.invoke(null, context, true, mObj); return result == 0; } catch (Throwable e) { return false; } } private static class InnerIdSupplier implements InvocationHandler { Context context; public InnerIdSupplier(Context context) { this.context=context; } @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { try { if ("OnSupport".equals(method.getName())) { boolean isSupport = (boolean) objects[0]; if (isSupport) { Object idSupplier = objects[1]; String oaid = (String) idSupplier.getClass().getDeclaredMethod("getOAID").invoke(idSupplier); Log.e("唯一id",oaid+""); Looper.prepare(); Toast.makeText(context,oaid,Toast.LENGTH_LONG).show(); Looper.loop(); // SpUtils.setString(Utils.getContext(), OAIDHelper.OAID, oaid); } return null; } return method.invoke(o, objects); } catch (Throwable e) { return null; } } }
3、使用
在项目初始化的时候调用getID(this)方法,会在InnerIdSupplier 里边生成唯一id保存起来使用即可。
如需获取sdk 关注公众号后 回复关键词 OAID 即可。
关注我获取更多知识或者投稿