独立游戏之路 -- 获取OAID提升广告收益
Unity 之 获取手机:OAID、IMEI、ClientId、GUID
- 前言
- 一、Oaid 介绍
- 1.1 Oaid 说明
- 1.2 移动安全联盟(MSA)
- 二、站在巨人的肩膀上
- 2.1 本文实现参考
- 2.2 本文实现效果
- 2.3 本文相关插件
- 三、Unity 中获取Oaid
- 3.1 查看实现源码
- 3.2 工程配置
- 3.3 代码实现
- 3.4 场景搭建
- 四、总结
前言
在当今的移动互联网时代,Oaid(Open Anonymous ID)成为了广告投放和用户分析的重要工具。对于 Unity 游戏开发者来说,获取安卓手机的 Oaid 可以帮助他们更好地了解用户行为、优化广告投放效果,并提供个性化的游戏体验。
我了解到Oaid还是在TapADN中,TapADN中提到Oaid可以提供更高收益:
本文将介绍如何在 Unity 中获取安卓手机的 Oaid。
一、Oaid 介绍
1.1 Oaid 说明
Oaid 是一种匿名设备标识符,用于标识移动设备。它与 IMEI 等设备标识符不同,Oaid 不会泄露用户的真实身份信息,同时也能满足广告投放和用户分析的需求。通过获取 Oaid,开发者可以了解用户的设备信息、地理位置、兴趣爱好等,从而为用户提供更加精准的广告投放和个性化的服务。
在 Android 10 版本中,广告渠道商们作为非厂商系统应用将无法获取 IMEI、MAC 等设备信息。旧版本的手机系统在用户手动升级前将保持不变,但是搭载 Android 10 系统的手机系统将不支持获取 IMEI。在一段时间内,将处于新旧版手机系统共存的状态,但是新版手机系统的用户占比将会逐渐提高,会造成新版系统用户无法进行推广渠道的匹配。
1.2 移动安全联盟(MSA)
(MSA)移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案,选择 OAID 字段作为 IMEI 等的替代字段 。广告渠道商选择 OAID 作为 IMEI 的替代字段。OAID 字段是由中国信通院联合华为、小米、OPPO、VIVO 等厂商共同推出的设备识别字段,具有一定的权威性。OAID 的准确性和覆盖率均满足广告场景的使用需求。
关于 OAID 更多信息可参考 MSA移动安全联盟官网: http://www.msa-alliance.cn/col.jsp?id=120
我注册并下载了MAD的SDK,看了开发说明文档,感觉集成操作有点复杂。进而有了本文的实现方式:
二、站在巨人的肩膀上
2.1 本文实现参考
查到了相关的实现方式【膜拜大佬】
参考链接:
- Unity Android获取OAID码
- Android_CN_OAID
2.2 本文实现效果
下图1是本文最终的实现效果,图2图3是1.3中大佬提供的apk的测试结果参照
2.3 本文相关插件
在文章开头的资源绑定中有源码和本文使用的最新library-4.2.8.aar包(下载地址),使用是可打开看下是否有新的。
开头提供的资源包内容:
三、Unity 中获取Oaid
3.1 查看实现源码
在 Unity 中,可以通过调用插件提供的接口来获取 Oaid。具体的获取方法可以参考DeviceIdentifier.java类代码。
一般来说,需要在游戏启动时获取 Oaid,并将其存储在本地,以便后续使用。
3.2 工程配置
在Project Setting→Player→安卓→Publishing Settings→Build 下勾选如下图所示三项,此时工程会自动生成左侧框到三个文件:
3.3 代码实现
在settingsTemplate.gradle,添加以下内容,粘贴两次,位置如图所示。
maven { url 'https://developer.huawei.com/repo/' }
maven { url 'https://developer.hihonor.com/repo' }
新建JAVA代码:
package com.GetOaid;import android.app.Application;
import android.app.Activity;import com.unity3d.player.UnityPlayer;import com.github.gzuliyujiang.oaid.DeviceIdentifier;
import com.github.gzuliyujiang.oaid.IRegisterCallback;public class OaidWrapper
{private Application application;public void register(){application = UnityPlayer.currentActivity.getApplication();DeviceIdentifier.register(application, false, new IRegisterCallback() {@Overridepublic void onComplete(String clientId, Exception error) {// do somethingUnityPlayer.UnitySendMessage("GetOaidSDK", "GetClientIdComplete", clientId);}});}public String getOAID(){UnityPlayer.UnitySendMessage("GetOaidSDK", "ShowMsg", DeviceIdentifier.getOAID(application));return DeviceIdentifier.getOAID(application);}public String getIMEI() {UnityPlayer.UnitySendMessage("GetOaidSDK", "ShowMsg", DeviceIdentifier.getIMEI(application));return DeviceIdentifier.getIMEI(application);}public String getClientId() {UnityPlayer.UnitySendMessage("GetOaidSDK", "ShowMsg", DeviceIdentifier.getClientId());return DeviceIdentifier.getClientId();}public String getGUID() {UnityPlayer.UnitySendMessage("GetOaidSDK", "ShowMsg", DeviceIdentifier.getGUID(application));return DeviceIdentifier.getGUID(application);}
}
3.4 场景搭建
创建两个Text展示获取到的信息,为了方便调试。在创建四个按钮用于测试主动获取OAID、IMEI、ClientId、GUID。新建GetOaidSDK
的物体挂载代码
新建测试代码:
- 需要将3.3中代码挂载到名为
GetOaidSDK
的物体上。 jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");
要和上面创建的java文件中的包名和类名对应上:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Android;
using UnityEngine.UI;public class GetOaidDemo : MonoBehaviour
{public Text oaidText;public Text megText;public Button getOaidBtn;public Button getIMEIBtn;public Button getClientIdBtn;public Button getGUIDBtn;public Button getOAIDAAIDBtn;private static AndroidJavaObject jo;// 读取设备信息 权限private string READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";void Start(){getOaidBtn.onClick.AddListener(OnClickGetOAID);getIMEIBtn.onClick.AddListener(OnClickGetIMEI);getClientIdBtn.onClick.AddListener(OnClickGetClientId);getGUIDBtn.onClick.AddListener(OnClickGetGUID);getOAIDAAIDBtn.onClick.AddListener(OnClickGetOAIDAAID);// 请求READ_PHONE_STATE权限RequestAndCheckPermission();}public void RequestAndCheckPermission(){Debug.Log("检查请求权限");if (!Permission.HasUserAuthorizedPermission(READ_PHONE_STATE)){Permission.RequestUserPermission(READ_PHONE_STATE);// 开始协程等待权限变化StartCoroutine(WaitForPermission(READ_PHONE_STATE));}else{// 权限已授予,执行操作Debug.Log("权限已授予,执行相关操作");Register();}}IEnumerator WaitForPermission(string permission){float timeWaited = 0f;const float timeout = 10f; // 设置超时时间,防止无限等待while (!Permission.HasUserAuthorizedPermission(permission) && timeWaited < timeout){yield return new WaitForSeconds(0.2f); // 暂停并检查权限状态timeWaited += 0.2f;}if (Permission.HasUserAuthorizedPermission(permission)){Debug.Log($"Permission {permission} granted after waiting.");// 在这里处理权限被授予的逻辑ShowMsg("这里可以执行需要该权限的操作.");}else{Debug.LogWarning($"Permission {permission} not granted after waiting.");// 处理权限请求超时或被拒绝的情况ShowMsg($"处理权限请求超时或被拒绝的情况.");}}public void Register(){if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");jo.Call("register");}}// 渠道clientId 自动获取oaidpublic void GetClientIdComplete(string clientId){oaidText.text = "clientId:" + clientId;OnClickGetOAID();}public void OnClickGetOAID(){oaidText.text += ",取Oaid:";if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");string oaidStr = jo.Call<string>("getOAID");oaidText.text += oaidStr;Debug.Log("取Oaid:" + oaidStr);}}public void OnClickGetOAIDAAID(){oaidText.text += ",getOAIDAAID:";if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");string oaidStr = jo.Call<string>("getOAIDAAID");oaidText.text += oaidStr;Debug.Log("getOAIDAAID:" + oaidStr);}}public void OnClickGetIMEI(){oaidText.text += ",getIMEI:";if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");string oaidStr = jo.Call<string>("getIMEI");oaidText.text += oaidStr;Debug.Log("getIMEI:" + oaidStr);}}public void OnClickGetClientId(){oaidText.text += ",getClientId:";if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");string oaidStr = jo.Call<string>("getClientId");oaidText.text += oaidStr;Debug.Log("getClientId:" + oaidStr);}}public void OnClickGetGUID(){oaidText.text += ",getGUID:";if (Application.platform == RuntimePlatform.Android){jo = new AndroidJavaObject("com.GetOaid.OaidWrapper");string oaidStr = jo.Call<string>("getGUID");oaidText.text += oaidStr;Debug.Log("getGUID:" + oaidStr);}}public void ShowMsg(string msg){megText.text += "\n" + msg;Debug.Log("msg:" + msg);}
}
四、总结
在获取和使用 Oaid 时,需要遵守相关的法律法规和隐私政策。不得将 Oaid 用于非法用途,不得泄露用户的隐私信息。
获取安卓手机的 Oaid 对于 Unity 游戏开发者来说具有重要的意义。通过获取 Oaid,开发者可以更好地了解用户行为、优化广告投放效果,并提供个性化的游戏体验。在获取 Oaid 时,需要遵守相关规定,确保获取的 Oaid 准确性,并及时更新 Oaid。希望本文对 Unity 游戏开发者有所帮助。
相关文章:
独立游戏之路 -- 获取OAID提升广告收益
Unity 之 获取手机:OAID、IMEI、ClientId、GUID 前言一、Oaid 介绍1.1 Oaid 说明1.2 移动安全联盟(MSA) 二、站在巨人的肩膀上2.1 本文实现参考2.2 本文实现效果2.3 本文相关插件 三、Unity 中获取Oaid3.1 查看实现源码3.2 工程配置3.3 代码实现3.4 场景搭建 四、总…...
反转链表 (oj题)
一、题目链接 https://leetcode.cn/problems/reverse-linked-list/submissions/538124207 二、题目思路 1.定义三个指针,p1先指向NULL p2指向头结点 p3指向第二个结点 2.p2的next指向p1。然后移动指针,p1来到p2的位置,p2来到p3的位置&…...
Mysql使用中的性能优化——批量插入的规模对比
在《Mysql使用中的性能优化——单次插入和批量插入的性能差异》中,我们观察到单次批量插入的数量和耗时呈指数型关系。 这个说明,不是单次批量插入的数量越多越好。本文我们将通过实验测试出本测试案例中最佳的单次批量插入数量。 结论 本案例中约每次…...
TCP为什么握手是三次,而挥手是四次
TCP(传输控制协议)使用三次握手(3WHS)来建立一个可靠的连接,并使用四次挥手(4WHS)来终止连接。以下是每个步骤的详细解释: 三次握手(3WHS)建立连接ÿ…...
前端面试题大合集9----TypeScript
目录 一、TypeScript 中静态类型的概念及其好处 二、如何在 TypeScript 的接口中定义可选属性? 三、解释 TypeScript 中联合类型的概念并提供示例 四、TypeScript 中的类型断言是什么? 五、TS中泛型是什么? 六、解释 TypeScript 中的“…...
Linux:动态库和静态库的编译与使用
目录 1.前言 2.静态链接库 3.静态链接库生成步骤 4.静态链接库的使用 5.动态链接库 6.动态链接库生成步骤 7.动态链接库的使用 8.动态链接库无法加载 9.解决动态链接库无法加载问题 前言 在《MinGW:从入门到链接库》博客中简单介绍了如何编译动态链接库和静态链接库…...
【Pyqt6 学习笔记】DIY一个二维码解析生成小工具
文章目录 Pycharm 配置QtDesignerPyUIC基本模板 代码示例依赖包main.pyscreen_shot_module.pyuntitled.pyuntitled.ui Pycharm 配置 摘自PyQT6的从零开始在Pycharm中配置与使用——蹦跑的蜗牛 pip install PyQt6 PyQt6-toolsQtDesigner File -> Settings -> External …...
关于xilinx srio ip复位问题
关于xilinx srio ip复位问题 语言 :Verilg HDL 、VHDL EDA工具: Vivado 关于xilinx srio ip复位问题一、引言二、FPGA 之间 srio通信复位处理复位时序不同步:SRIO 模块未正确初始化:等待复位完成的时间不足:SRIO 配置…...
04 uboot 编译与调试
新手不需要详细掌握 uboot,只需要知道它是一个什么东西即可,工作中也只是改一些参数而已。 1、uboot 是什么 Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段 bootloader 程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将 Linux 内…...
【机器学习】机器学习与医疗健康在智能诊疗中的融合应用与性能优化新探索
文章目录 引言机器学习与医疗健康的基本概念机器学习概述监督学习无监督学习强化学习 医疗健康概述疾病预测诊断辅助个性化治疗方案制定 机器学习与医疗健康的融合应用实时健康监测数据预处理特征工程 疾病预测与优化模型训练模型评估 诊断辅助与优化深度学习应用 个性化治疗方…...
在线OJ项目测试(selenium+Junit5)
目录 在线OJ项目测试的思维导图 在线OJ的UI自动化测试 测试一:检查未登录时的页面访问以及一些未登录时的非法操作 测试二:测试注册界面 测试三:测试登录界面 测试四:测试题目列表界面 测试五:测试题目详情界面…...
计算机系统基础笔记(12)——控制
前言 在持续输出ing 一、条件码 1.处理器状态(x86-64,部分的) 当前程序的执行信息 ◼ 临时数据 ◼ 运行时栈的位置(栈顶) ◼ 当前代码控制点的位置(即将要执行的指令地址) ◼ 最近一次指令执…...
使用RedissonClient的管道模式批量查询key
1.场景 遇到了一个场景,在客户给我们推送的数据中,咋1分钟左右,会有相同车辆vehicle 和时间 gpstime一样的数据,这类数据呢,我们认为是重复数据,需要过滤的 把相同 vehicle 和 gpstime 作为key存入到redis中…...
UR机器人通信汇总
文章目录 一、概述二、UR机器人通信2.1UR通信协议2.2 UR通信端口 三、UR机器人通信端口类型3.1 Modbus TCP端口(502端口)3.2 Dashboard端口(29999端口)3.3 上位机编程端口(30001/30002/30003端口)3.3.1 URS…...
AI学习指南机器学习篇-使用ID3算法构建决策树
AI学习指南机器学习篇-使用ID3算法构建决策树 介绍ID3算法 ID3(Iterative Dichotomiser 3)是一种用于构建决策树的经典机器学习算法。它是由Ross Quinlan于1986年提出的,是一种基于信息论的算法,用于从一组特征中选择最佳特征来…...
React实战(一)初始化项目、配置router、redux、axios
(一)初始化项目 1.安装项目 npx create-react-app 项目名 编译报错: 解决办法:安装最新的babel-preset-react-app npm install babel-preset-react-applatest 2.配置项目 (1)配置文件目录 (2)使用craco配置webpack.config npm install craco/crac…...
高质量 HarmonyOS 权限管控流程
高质量 HarmonyOS 权限管控流程 在 HarmonyOS 应用开发过程中,往往会涉及到敏感数据和硬件资源的调动和访问,而这部分的调用就会涉及到管控这部分的知识和内容了。我们需要对它有所了解,才可以在应用开发中提高效率和避免踩坑。 权限管控了…...
java里面封装https请求工具类2
其他写法 https://blog.csdn.net/weixin_44372802/article/details/132620809?spm1001.2014.3001.5501 encodeJson 是请求参数的密文格式(大公司都是要对请求参数加密的) ResponseBean 是自己或者对方定义的返回内容参数 public ResponseBean sendByEnc…...
前端面试题日常练-day59 【面试题】
题目 希望这些选择题能够帮助您进行前端面试的准备,答案在文末 1. 在PHP中,以下哪个符号用于比较两个值的相等性? a) b) c) d) ! 2. PHP中的预定义变量$_POST用于获取什么类型的数据? a) 用户的输入数据 b) 浏览器发送的请…...
计算机小问题(4)--关闭联想电脑的小组件
打开联想软件管家,关闭即可 (今天弄了好久才找到,记录一下)...
mac无法读取windows分区怎么办 苹果硬盘怎么读取
对于Mac电脑用户但有Windows系统使用需求的,我们可以通过Boot Camp启动转换助理安装Windows分区这个方案来解决,不过因为两个系统的磁盘格式不同,相应的也会产生一些问题,例如无法正常读取windows分区。下面本文就详细说明mac无法…...
【设计模式】JAVA Design Patterns——State(状态模式)
🔍目的 允许对象在内部状态改变时改变它的行为。对象看起来好像修改了它的类。 🔍解释 真实世界例子 当在长毛象的自然栖息地观察长毛象时,似乎它会根据情况来改变自己的行为。它开始可能很平静但是随着时间推移当它检测到威胁时它会对周围的…...
Docker搭建可道云
Docker搭建可道云(存储) 文章目录 Docker搭建可道云(存储)介绍资源列表基础环境一、安装Docker二、配置Docker加速器三、搭建可道云私有云盘3.1、编写Dockerfile3.2、上传资源到指定目录3.3、查看目录下所有资源 四、构建镜像五、…...
【RISC-V】站在巨人的肩膀上——看开源芯片、软件生态、与先进计算/人工智能/安全的结合
目录 会议议程前言开源处理器芯片的机遇与挑战,孙凝晖,中国工程院院士RISC-V原生基础软件栈,武延军,中国科学院软件研究所RISC-V推动新型架构创新,孟建熠,浙江大学 专题一:开源芯片开源高性能 R…...
test 判断字符串不为空
#!/bin/bash read -p "请输入参数:" name test -z $name if [ $? -eq 1 ]; then echo "入参:$name" else echo "入参为null" fi...
Python数据分析I
目录 注:简单起见,下文中"df"均写为"表名","函数"均写为"HS","属性"均写为"SX","范围"均写为"FW"。 1.数据分析常用开源库 注释…...
Qt5/6使用SqlServer用户连接操作SqlServer数据库
网上下载SQLServer2022express版数据库,这里没啥可说的,随你喜欢,也可以下载Develop版本。安装完后,我们可以直接连接尝试, 不过一般来说,还是下载SQLServer管理工具来连接数据更加方便。 所以直接下载ssms, 我在用的时候,一开始只能用Windows身份登录。 所以首先,我…...
[经验] 场效应管是如何发挥作用的 #知识分享#学习方法#职场发展
场效应管是如何发挥作用的 在现代电子技术领域,场效应管(MOSFET)是一种重要的半导体元器件。它的作用非常广泛,例如在集成电路中扮演着关键的角色。在本文中,我们将详细探讨场效应管的作用及其在实际应用中的意义。 简…...
数据挖掘--分类
数据挖掘--引论 数据挖掘--认识数据 数据挖掘--数据预处理 数据挖掘--数据仓库与联机分析处理 数据挖掘--挖掘频繁模式、关联和相关性:基本概念和方法 数据挖掘--分类 数据挖掘--聚类分析:基本概念和方法 基本概念 决策树归纳 决策树:决策树是一…...
数据结构篇其六-串
数据结构—串 前置说明 由于学习Java面向对象语言走火入魔,试图在C语言中模拟实现面向对象设计。里面加入了大量的函数指针配合结构体来模拟类中的成员方法 故此篇,亦可称: 面向对象的C语言程序设计 用C语言实现串这种数据结构,并将它应用到…...
wap开头的网站/市场调研报告范文
【出版商】贝哲斯咨询 【免费目录下载】网上团购是一种以最低的价格给消费者提供产品和服务,但前提是必须有最少数量的购买者进行购买的一种购物方式。 网上团购市场的企业竞争态势 该报告涉及的主要国际市场参与者有Amazon、Alibaba、Groupon、Plum District、Cr…...
wordpress 嵌入播放ppt/上海网站seo
开发软件,包括linux版 jdk,mysql,nginx,tomcat,redis,软件日志文件(测试使用) 有可能底下需要使用,如果需要请自行下载 链接:https://pan.baidu.com/s/1xhdD…...
没有数据怎么做网站/国家免费职业培训平台
最近有空就着迷于java的世界,希望可以把自己的lind重构一个java版本出来,虽然遇到一些小问题,但也都解决了,还是那句话,知识需要积累,程序员需要一个追求! 类抽象类接口泛型类泛型接口非泛型类继…...
政府网站栏目建设反馈意见/直销怎么做才最快成功
axios 安装 npm install axios React中配置代理解决跨域问题 方法一 在package.json中追加如下配置 "proxy":"http://localhost:5000"说明: 优点:配置简单,前端请求资源时可以不加任何前缀。缺点:不能配…...
优化站诊断/腾讯第三季度营收448亿元
mouseover定义和用法 当鼠标指针位于元素上方时,会发生 mouseover 事件。 该事件大多数时候会与 mouseout 事件一起使用。 mouseover() 方法触发 mouseover 事件,或规定当发生 mouseover 事件时运行的函数。 注释:与 mouseenter 事件不同&…...
专业网站定制 北京/百度竞价排名广告定价鲜花
1. 前言 随着信息技术和互联网的发展, 我们已经步入了一个信息过载的时代,这个时代,无论是信息消费者还是信息生产者都遇到了很大的挑战: 信息消费者:如何从大量的信息中找到自己感兴趣的信息?信息生产者…...