世界杯加纳

Android中使用OAID

关于

因传统的移动终端设备标识如国际移动设备识别码(IMEI)等已被部分国家认定为用户隐私的一部分,并存在被篡改和冒用的风险,所以在Android 10及后续版本中非厂商系统应用将无法获取IMEI、MAC等设备信息。无法获取IMEI会在用户行为统计过程中对设备识别产生一定影响。近日移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案,选择OAID字段作为IMEI等的替代字段。OAID字段是由中国信通院联合华为、小米、OPPO、VIVO等厂商共同推出的设备识别字段,具有一定的权威性,可满足用户行为统计的使用场景。

移动安全联盟官网: 移动安全联盟刚官网地址 安全联盟SDK、文档以及申请表格: 安全联盟SDK1.0.29文档及SDK

目前支持的机型

厂商名称支持版本华为HMS 2.6.2 及以上小米MIUI 10.2 及以上版本vivoAndroid 9 及以上版本OPPOcolorOS 6 大部分覆盖,colorOS 7 及以上全覆盖联想ZUI 11.4 及以上版本三星Android 10 版本魅族Android 10 版本努比亚Android 10 版本中兴Android 10 版本华硕Android 10 版本一加Android 10 版本黑鲨Android 10 版本摩托罗拉Android 10 版本Freeme OSAndroid 10 版本酷赛(铂睿智恒)Android 10 版本RealmecolorOS 6 大部分覆盖,colorOS 7 及以上全覆盖荣耀Android 10 版本

调用方法

接入准备——申请证书文件(将需要申请的app信息填写到example_batch.csv表格,然后发送到msa@caict.ac.cn进行申请。注意每个包名对应一个签名,申请时需要将需要申请的全部包名填写到表格中。申请后安全联盟将会把所有申请的证书发送到申请时使用的邮箱)

注意: 关于example_batch.csv表格 表格中的会员账号:是指在安全联盟登录的账号 可点击进入安全联盟登录页面 表格中的邮箱:最好填写安全联盟登录账号绑定的邮箱

把oaid_sdk_x.x.x.aar拷贝到项的libs目录,并设置依赖,其中x.x.x代 表版本号。最新的版本为1.0.29

将证书文件(应用包名.cert.pem)、 supplierconfig.json 文件拷贝到项目 assets 目录下,(只获取oaid信息则不需要修改json配置文件,只需原样放到assets目录下即可。如果想要使用VAID,可修改里边对应内容,特别是需要设置 appid 的部分,要去对应厂商的应用商店里注册自己的 app,来获取对应appid。)

设置依赖

implementation files(‘libs/oaid_sdk_1.0.29.aar’)

混淆设置

# sdk

-keep class com.bun.miitmdid.** { *; }

# asus

-keep class com.asus.msa.SupplementaryDID.** { *; }

-keep class com.asus.msa.sdid.** { *; }

# freeme

-keep class com.android.creator.** { *; }

-keep class com.android.msasdk.** { *; }

# huawei

-keep class com.huawei.hms.ads.identifier.** { *; }

#-keep class com.uodis.opendevice.aidl.** { *; }

# lenovo

-keep class com.zui.deviceidservice.** { *; }

-keep class com.zui.opendeviceidlibrary.** { *; }

# meizu

-keep class com.meizu.flyme.openidsdk.** { *; }

# nubia

-keep class com.bun.miitmdid.provider.nubia.NubiaIdentityImpl

# oppo

-keep class com.heytap.openid.** { *; }

# samsung

-keep class com.samsung.android.deviceidservice.** { *; }

# vivo

-keep class com.vivo.identifier.** { *; }

# xiaomi

-keep class com.bun.miitmdid.provider.xiaomi.IdentifierManager

# zte

-keep class com.bun.lib.** { *; }

# coolpad

-keep class com.coolpad.deviceidsupport.** { *; }

设置 gradle 编译选项,开发者可以根据自己对平台的选择进行合理配置

ndk { abiFilters 'armeabi-v7a','x86','arm64-v8a','x86_64','armeabi' }

注意:考虑到 sdk 兼容性,sdk 包默认集成了常用 abi 的 so,包括 armeabi-v7a,arm64-v8a, x84, x84_64 共四种。如果需要减小 SDK 体积,可以使用压缩工具打开 aar 文件,手动删除多余的架构。

添加 oaid管理文件MiitHelper.java

根据官网源文件DemoHelper.java修改而来,可以根据自己需求修改,这里是cocos工程,这里将文件MiitHelper.java放到org.cocos2dx.javascript目录中。

package org.cocos2dx.javascript;

import android.content.Context;

import android.util.Log;

import com.bun.miitmdid.core.InfoCode;

import com.bun.miitmdid.core.MdidSdkHelper;

import com.bun.miitmdid.interfaces.IIdentifierListener;

import com.bun.miitmdid.interfaces.IdSupplier;

import com.bun.miitmdid.pojo.IdSupplierImpl;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

public class MiitHelper implements IIdentifierListener {

public static final String TAG = "MiitHelper";

public static final int HELPER_VERSION_CODE = 20210928; // DemoHelper版本号

private AppIdsUpdater appIdsUpdater;

private boolean isCertInit = false;

public final boolean isSDKLogOn = true; // 1)设置 是否开启sdk日志

public static String ASSET_FILE_NAME_CERT = ""; // 2)设置 asset证书文件名

public static void Init(Context context, AppIdsUpdater listener){

MiitHelper miitHelper = new MiitHelper();

ASSET_FILE_NAME_CERT = context.getPackageName()+".cert.pem";

Log.e(TAG,ASSET_FILE_NAME_CERT);

System.loadLibrary("nllvm1632808251147706677"); // 加固版本在调用前必须载入SDK安全库

if(MdidSdkHelper.SDK_VERSION_CODE != HELPER_VERSION_CODE){

Log.w(TAG,"SDK version not match.");

throw new RuntimeException("SDK version not match.");

}

miitHelper.appIdsUpdater = listener;

// 获取设备号

miitHelper.getDeviceIds(context);

}

/**

* 获取OAID

* @param cxt

*/

public void getDeviceIds(Context cxt){

// TODO (4)初始化SDK证书

if(!isCertInit){ // 证书只需初始化一次

// 证书为PEM文件中的所有文本内容(包括首尾行、换行符)

isCertInit = MdidSdkHelper.InitCert(cxt, loadPemFromAssetFile(cxt, ASSET_FILE_NAME_CERT));

if(!isCertInit){

Log.w(TAG, "getDeviceIds: cert init failed");

}

}

//(可选)设置InitSDK接口回调超时时间(仅适用于接口为异步),默认值为5000ms.

// 注:请在调用前设置一次后就不再更改,否则可能导致回调丢失、重复等问题

MdidSdkHelper.setGlobalTimeout(5000);

// TODO (5)调用SDK获取ID

int code = MdidSdkHelper.InitSdk(cxt, isSDKLogOn, this);

// TODO (6)根据SDK返回的code进行不同处理

IdSupplierImpl unsupportedIdSupplier = new IdSupplierImpl();

if(code == InfoCode.INIT_ERROR_CERT_ERROR){ // 证书未初始化或证书无效,SDK内部不会回调onSupport

// APP自定义逻辑

Log.w(TAG,"cert not init or check not pass");

onSupport(unsupportedIdSupplier);

}else if(code == InfoCode.INIT_ERROR_DEVICE_NOSUPPORT){ // 不支持的设备, SDK内部不会回调onSupport

// APP自定义逻辑

Log.w(TAG,"device not supported");

onSupport(unsupportedIdSupplier);

}else if( code == InfoCode.INIT_ERROR_LOAD_CONFIGFILE){ // 加载配置文件出错, SDK内部不会回调onSupport

// APP自定义逻辑

Log.w(TAG,"failed to load config file");

onSupport(unsupportedIdSupplier);

}else if(code == InfoCode.INIT_ERROR_MANUFACTURER_NOSUPPORT){ // 不支持的设备厂商, SDK内部不会回调onSupport

// APP自定义逻辑

Log.w(TAG,"manufacturer not supported");

onSupport(unsupportedIdSupplier);

}else if(code == InfoCode.INIT_ERROR_SDK_CALL_ERROR){ // sdk调用出错, SSDK内部不会回调onSupport

// APP自定义逻辑

Log.w(TAG,"sdk call error");

onSupport(unsupportedIdSupplier);

} else if(code == InfoCode.INIT_INFO_RESULT_DELAY) { // 获取接口是异步的,SDK内部会回调onSupport

Log.i(TAG, "result delay (async)");

}else if(code == InfoCode.INIT_INFO_RESULT_OK){ // 获取接口是同步的,SDK内部会回调onSupport

Log.i(TAG, "result ok (sync)");

}else {

// sdk版本高于DemoHelper代码版本可能出现的情况,无法确定是否调用onSupport

// 不影响成功的OAID获取

Log.w(TAG,"getDeviceIds: unknown code: " + code);

}

}

/**

* APP自定义的getDeviceIds(Context cxt)的接口回调

* @param supplier

*/

@Override

public void onSupport(IdSupplier supplier) {

if(supplier==null) {

Log.w(TAG, "onSupport: supplier is null");

return;

}

if(appIdsUpdater ==null) {

Log.w(TAG, "onSupport: callbackListener is null");

return;

}

// 获取Id信息

// 注:IdSupplier中的内容为本次调用MdidSdkHelper.InitSdk()的结果,不会实时更新。 如需更新,需调用MdidSdkHelper.InitSdk()

boolean isSupported = supplier.isSupported();

boolean isLimited = supplier.isLimited();

String oaid=supplier.getOAID();

String vaid=supplier.getVAID();

String aaid=supplier.getAAID();

//TODO (7) 自定义后续流程,以下显示到UI的示例

String idsText= "support: " + (isSupported ? "true" : "false") +

"\nlimit: " + (isLimited ? "true" : "false") +

"\nOAID: " + oaid +

"\nVAID: " + vaid +

"\nAAID: " + aaid + "\n";

Log.d(TAG, "onSupport: ids: \n" + idsText);

appIdsUpdater.onIdsValid(oaid);

}

public interface AppIdsUpdater {

void onIdsValid(String oaid);

}

/**

* 从asset文件读取证书内容

* @param context

* @param assetFileName

* @return 证书字符串

*/

public static String loadPemFromAssetFile(Context context, String assetFileName){

try {

InputStream is = context.getAssets().open(assetFileName);

BufferedReader in = new BufferedReader(new InputStreamReader(is));

StringBuilder builder = new StringBuilder();

String line;

while ((line = in.readLine()) != null){

builder.append(line);

builder.append('\n');

}

return builder.toString();

} catch (IOException e) {

Log.e(TAG, "loadPemFromAssetFile failed");

return "";

}

}

}

调用

在Activity的onCreate函数中添加初始化。这是异步调用,使用需要注意一下。

public class AppActivity extends Cocos2dxActivity implements ActivityCompat.OnRequestPermissionsResultCallback {

public static String oaid = "";

...

@Override

protected void onCreate(Bundle savedInstanceState) {

...

MiitHelper.Init(this, new MiitHelper.AppIdsUpdater(){

@Override

public void onIdsValid(String oaid){

AppActivity.oaid = oaid;

}

});

}

....

}

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。 相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集

二、源码解析合集

三、开源框架合集 欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题