在 Android 10 版本中,广告渠道商们作为非厂商系统应用将无法获取 IMEI、MAC 等设备信息。旧版本的手机系统在用户手动升级前将保持不变,但是搭载 Android 10 系统的手机系统将不支持获取 IMEI。在一段时间内,将处于新旧版手机系统共存的状态,但是新版手机系统的用户占比将会逐渐提高,会造成新版系统用户无法进行推广渠道的匹配。
(MSA)移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案,选择 OAID 字段作为 IMEI 等的替代字段 。广告渠道商选择 OAID 作为 IMEI 的替代字段。OAID 字段是由中国信通院联合华为、小米、OPPO、VIVO 等厂商共同推出的设备识别字段,具有一定的权威性。OAID 的准确性和覆盖率均满足广告场景的使用需求。
关于 OAID 更多信息可参考 MSA移动安全联盟官网: http://www.msa-alliance.cn/col.jsp?id=120
方法一:
进入MSA移动安全联盟官网: http://www.msa-alliance.cn/col.jsp?id=120 下载miit_mdid_x.x.x.aar
方法二:
如果官网找不到下载的地方,就进入我自己的链接下吧
链接:https://pan.baidu.com/s/1ES9_tmQqZt0E7FApwhzVXQ
提取码:x3fo
进入目录miit_mdid_sdk_v1.0.13
,可以看到一个aar文件
把.aar
改成.zip
,然后解压再进入msa_mdid_1.0.13
可以看到一个classes.jar,这个就是我们的目标jar文件,把他重命名为msa_mdid_1.0.13.jar
把msa_mdid_1.0.13.jar
丢到Unity的Assets/Plugins/Android/libs
目录中;
把AndroidManifest.xml
中的权限加到Unity中的Assets/Plugins/Android/AndroidManifest.xml
中;
把assets
目录中的dex文件丢到Unity的Assets/Plugins/Android/assets
目录中;
把上一层目录的supplierconfig.json
也丢到Unity的Assets/Plugins/Android/assets
目录中;
把jni
目录中的armeabi
、armeabi-v7a
、x86
丢到Unity的Assets/Plugins/Android/libs
目录中。
最后,Unity的Assets/Plugins
目录结构如下:
创建Android工程,包名和Unity的包名一致,比如我的这个工程包名是:com.linxinfa.oaidtest
因为要和Unity交互,所以先要导入Unity的jar包。
右键Android工程,点击Properties菜单,点击Java Build Path
,再点击Add External JARs...
,选择Unity的classes.jar
,在Unity安装目录中可以找到这个classes.jar
。
比如我的是
F:\Unity5.5.5\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
然后再导入上文提到的msa_mdid_1.0.13.jar
。
把sdk文件中的MiitHelper.java直接拷过来,改下顶部的package为当前包名:
打开MainActivity.java
,使其继承UnityPlayerActivity
。
封装一个GetOAID
接口,MainActivity.java
代码如下:
package com.linxinfa.oaidtest;
import android.os.Bundle;
import com.bun.miitmdid.core.ErrorCode;
import com.bun.miitmdid.core.JLibrary;
import com.bun.miitmdid.core.MdidSdkHelper;
import com.bun.supplier.IIdentifierListener;
import com.bun.supplier.IdSupplier;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;
public class MainActivity extends UnityPlayerActivity{
private long timeb, timee;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
JLibrary.InitEntry(MainActivity.this);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//初始化
}
public void GetOAID()
{
timeb = System.currentTimeMillis();
int errorCode = MdidSdkHelper.InitSdk(MainActivity.this, true, new IIdentifierListener() {
@Override
public void OnSupport(boolean b, IdSupplier idSupplier) {
if (idSupplier == null) {
return;
}
SendToUnity("OAID=" + idSupplier.getOAID());
timee = System.currentTimeMillis();
SendToUnity("耗时:" + (timee - timeb) + "毫秒");
}
});
if (errorCode == ErrorCode.INIT_ERROR_DEVICE_NOSUPPORT) {
SendToUnity("获取OAID:" + "不支持的设备");
} else if (errorCode == ErrorCode.INIT_ERROR_LOAD_CONFIGFILE) {
SendToUnity("获取OAID:" + "加载配置文件出错");
} else if (errorCode == ErrorCode.INIT_ERROR_MANUFACTURER_NOSUPPORT) {
SendToUnity("获取OAID:" + "不支持的设备厂商");
} else if (errorCode == ErrorCode.INIT_ERROR_RESULT_DELAY) {
SendToUnity("获取OAID:" + "获取接口是异步的,结果会在回调中返回,回调执行的回调可能在工作线程");
} else if (errorCode == ErrorCode.INIT_HELPER_CALL_ERROR) {
SendToUnity("获取OAID:" + "反射调用出错");
} else {
SendToUnity("获取OAID:" + "获取成功");
}
}
// 发送消息给Unity
private void SendToUnity(String msg)
{
UnityPlayer.UnitySendMessage("Main Camera", "OnJavaMsg", msg);
}
}
右键Android工程,点击Export...
,选择Jar file
,最后导出为game.jar
。
然后把game.jar
丢到Unity的Assets/Plugins/Android/libs
目录中
在Assets/Plugins/Android
目录中,要有个AndroidManifest.xml文件。
注意package包名为,比如我的是:com.linxinfa.oaidtest
。
添加sdk的权限。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
//asus permisstion
<uses-permission android:name="com.asus.msa.SupplementaryDID.ACCESS" />
把启动Activity改为.MainActivity
。
最终如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.linxinfa.oaidtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
//asus permisstion
<uses-permission android:name="com.asus.msa.SupplementaryDID.ACCESS" />
<application
android:icon="@drawable/app_icon"
android:label="@string/app_name"
android:debuggable="false"
android:allowBackup="false">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
android:launchMode="singleTop"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
application>
manifest>
创建些简单的UI,写个Main.cs
脚本,挂到Main Camera
上,给Main脚本的UI成员赋值。
Main.cs代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Main : MonoBehaviour
{
public Text logLbl;
public Button getOaidBtn;
void Start()
{
logLbl.text = "";
Application.logMessageReceived += LogCallback;
getOaidBtn.onClick.AddListener(() =>
{
using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))
{
// 调用java接口
jo.Call("GetOAID");
}
}
});
}
// java那边通过UnityPlayer.UnitySendMessage发送过来的消息
public void OnJavaMsg(string msg)
{
Debug.Log(msg);
}
// 日志监听
public void LogCallback(string condition, string stackTrace, LogType type)
{
logLbl.text += condition + "\n";
}
}