当前位置: 首页 > news >正文

Android 系统中适配OAID获取

一、OAID概念

OAID(Open Anonymous Identification)是一种匿名身份识别标识符,
用于在移动设备上进行广告追踪和个性化广告投放。它是由中国移动通信集
团、中国电信集团和中国联通集团共同推出的一项行业标准
OAID值为一个64位的数字

二、OAID产生的背景

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

三、由于OAID 引发的问题

环境:高通865 Android10 虚拟化

1、问题现象

第三方游戏应用集成了移动联盟sdk获取oaid,但是系统并没有适配oaid,导致第三方应用集成移动联盟sdk获取oaid时获取为空导致应用闪退。

2、解决思路

(1)、编写一个apk,集成到系统,开机自启,应用中定义了一个服务和重写了相对应的获取oaid的接口
(2)、定义一个oaid属性值,persist.oaid用来设置和获取oaid值
(3)、第三方应用调用移动联盟sdk获取oaid时,调用步骤1中重写的获取oaid接口,该接口通过属性值persist.oaid读取oaid的值,返回给第三方应用,这样就可以避免获取到oaid值为空情况。

3、处理步骤

3.1 编写apk,这里以适配OPPO厂商为例,每种厂商有可能重写的接口和方式不一样,这里需要注意。oppo厂商的代码如下,具体的可以下载源码查看。

BootCompletedReceiver.java代码如下:
package com.heytap.openid;import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;import java.util.List;public class BootCompletedReceiver extends BroadcastReceiver {//    private final String ACTION_BOOT_COMPLETED = "com.matrixlauncher.oncreate"; //开机Launcher广播private final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; //系统开机广播@Overridepublic void onReceive(Context context, Intent intent) {if (intent != null) {Log.d("CCCCC", "Oppo BootCompletedReceiveronReceive");if (!TextUtils.isEmpty(intent.getAction()) && intent.getAction().equals(ACTION_BOOT_COMPLETED)) {if (!isRun(context)) {Log.d("CCCCC", "Oppo BootCompletedReceiveronReceive start IdentifyService");context.startService(new Intent(context, IdentifyService.class));}}}}/*** 判断应用是否在运行** @param context* @return*/public boolean isRun(Context context) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);List<ActivityManager.RunningTaskInfo> list = am.getRunningTasks(100);boolean isAppRunning = false;String MY_PKG_NAME = "com.heytap.openid";//100表示取的最大的任务数,info.topActivity表示当前正在运行的Activity,info.baseActivity表系统后台有此进程在运行for (ActivityManager.RunningTaskInfo info : list) {if (info.topActivity.getPackageName().equals(MY_PKG_NAME) || info.baseActivity.getPackageName().equals(MY_PKG_NAME)) {isAppRunning = true;break;}}return isAppRunning;}
}
IdentifyService.java代码如下:
package com.heytap.openid;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;import androidx.annotation.Nullable;public class IdentifyService extends Service {@Overridepublic void onCreate() {super.onCreate();Log.d("CCCCC", "Oppo IdentifyService onCreate()");}@Nullable@Overridepublic IBinder onBind(Intent intent) {return binder;}private final IOpenID.Stub binder = new IOpenID.Stub() {@Overridepublic String getSerID(String pkgName, String sign, String type) throws RemoteException {Log.d("CCCCC", "Oppo OpenDeviceIdentifierService.Stub getOaid=" + SysProp.get("persist.oaid", ""));return SysProp.get("persist.oaid", "");}};
}

IOpenID.aidl代码如下:

// IOpenID.aidl
package com.heytap.openid;// Declare any non-default types here with import statementsinterface IOpenID {String getSerID(String pkgName, String sign, String type);
}

AndroidManifest.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.heytap.openid"android:sharedUserId="android.uid.system"><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><!-- 开机广播 --><receiverandroid:name=".BootCompletedReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.matrixlauncher.oncreate" /><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver><service android:name=".IdentifyService"android:enabled="true"android:exported="true"><intent-filter><action android:name="action.com.heytap.openid.OPEN_ID_SERVICE" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></application></manifest>

代码结构如下,注意:包名那些都是固定的:


文章末尾会附上相关资料和适配华为、OPPO、三星、Vivo的应用服务源码

3.2 将编译好的apk集成到系统(集成apk的文件和位置仅供参考,有可能不一样,示例集成 OppoAnonymousId.apk)

3.2.1 Qualcomm865_vir/vendor/qcom/proprietary/prebuilt_HY11/target/product/qssi/prebuilt.mk中添加

PRODUCT_PACKAGES += OppoAnonymousId

3.2.2  Qualcomm865_vir/device/qcom/qssi/system.prop中新增属性

#oaid 
persist.oaid=0

3.2.3  Qualcomm865_vir/frameworks/base/core/java/android/app/ActivityThread.java中修改manufacturer值

3.2.4 /home/wenyang/workplace/code/Qualcomm865_vir/vendor/qcom/proprietary/prebuilt_HY11/target/product/qssi/Android.mk中新增需要集成的apk

include $(CLEAR_VARS)
LOCAL_MODULE        := OppoAnonymousId
LOCAL_MODULE_OWNER  := qcom
LOCAL_MODULE_TAGS   := optional
LOCAL_MODULE_CLASS  := APPS
LOCAL_CERTIFICATE   := platform
LOCAL_MODULE_SUFFIX := .apk
LOCAL_SRC_FILES     := ../../.././target/product/qssi/system/app/OppoAnonymousId/OppoAnonymousId.apk
LOCAL_MULTILIB := 64
LOCAL_MODULE_PATH   := $(PRODUCT_OUT)/system/app
include $(BUILD_PREBUILT)

3.2.5 device/qcom/qssi/apps_white_list.txt和 device/qcom/kona/apps_white_list.txt中添加OppoAnonymousId,如下图所示:

3.3 修改设备厂商为OPPO(和3.2.3步骤重复,建议采用3.2.3改机的形式修改,如果采用改机形式修改 ro.product.manufacturer属性值,此步骤可忽略)
 ro.product.manufacturer=OPPO
3.4 修改设备厂商后,安装测试oaid test_get_oaid.apk,看看是否支持获取oaid

4、验证

4.1查看应用是否存在

 pm list packages | grep com.heytap.openid

如果服务正常启动,通过上面的命令,可以查到如下结果:

或者通过如下命令查看进程是否存在:

ps  -A |  grep  com.heytap.openid

4.2查看是否有调用重写的接口

第三方应用获取oaid时,是否有调用我们写的apk aidl中的接口,这里以oppo为例,查看日志会调用下面的接口:

oaid适配应用源码和相关资料下载链接: https://download.csdn.net/download/banzhuantuqiang/88331871

相关文章:

Android 系统中适配OAID获取

一、OAID概念 OAID&#xff08;Open Anonymous Identification&#xff09;是一种匿名身份识别标识符&#xff0c; 用于在移动设备上进行广告追踪和个性化广告投放。它是由中国移动通信集 团、中国电信集团和中国联通集团共同推出的一项行业标准 OAID值为一个64位的数字 二、…...

差分数组leetcode 2770 数组的最大美丽值

什么是差分数组 差分数组是一种数据结构&#xff0c;它存储的是一个数组每个相邻元素的差值。换句话说&#xff0c;给定一个数组arr[]&#xff0c;其对应的差分数组diff[]将满足&#xff1a; diff[i] arr[i1] - arr[i] 对于所有 0 < i < n-1 差分数组的作用 用于高效…...

请求响应状态码

请求与响应&状态码 Requests部分 请求行、消息报头、请求正文。 Header解释示例Accept指定客户端能够接收的内容类型Accept: text/plain, text/htmlAccept-Chars et浏览器可以接受的字符编码集。Accept-Charset: iso-8859-5Accept-Encodi ng指定浏览器可以支持的web服务…...

安卓机型系统美化 Color.xml文件必备常识 自定义颜色资源

color.xml文件是Android工程中用来进行颜色资源管理的文件.可以在color.xml文件中通过<color>标签来定义颜色资源.我们在布局文件中、代码中、style定义中或者其他资源文件中&#xff0c;都可以引用之前在color.xml文件中定义的颜色资源。 将color.xml文件拷到res/value…...

YOLO物体检测-系列教程1:YOLOV1整体解读(预选框/置信度/分类任/回归任务/损失函数/公式解析/置信度/非极大值抑制)

&#x1f388;&#x1f388;&#x1f388;YOLO 系列教程 总目录 YOLOV1整体解读 YOLOV2整体解读 YOLOV1提出论文&#xff1a;You Only Look Once: Unified, Real-Time Object Detection 1、物体检测经典方法 two-stage&#xff08;两阶段&#xff09;&#xff1a;Faster-rc…...

2023/9/12 -- C++/QT

作业 实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xf…...

【Purple Pi OH RK3566鸿蒙开发板】OpenHarmony音频播放应用,真实体验感爆棚!

本文转载于Purple Pi OH开发爱好者&#xff0c;作者ITMING 。 原文链接&#xff1a;https://bbs.elecfans.com/jishu_2376383_1_1.html 01注意事项 DevEco Studio 4.0 Beta2&#xff08;Build Version: 4.0.0.400&#xff09; OpenHarmony SDK API 9 创建工程类型选择Appli…...

Android rom开发:9.0系统上实现4G wifi 以太网共存

framework层修改网络优先级&#xff0c;4G > wifi > eth 修改patch如下&#xff1a; diff --git a/frameworks/base/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/frameworks/base/services/core/java/com/android/server/connectivit…...

高速自动驾驶HMI人机交互

概述 目的 本文档的目的是描述高速自动驾驶功能涉及的HMI显示需求技术规范和设计说明。 范围 术语及缩写 设计与实验标准 设计标准 设计标准-非法规类设计标准-法规类 HMI交互需求 CL4功能界面 HMI显示器[伊1] 中应包含CL4功能设置界面&#xff0c;提供给用户进行设置操作或显…...

【自然语言处理】关系抽取 —— SOLS 讲解

SOLS 论文信息 标题:Speaker-Oriented Latent Structures for Dialogue-Based Relation Extraction 作者:Guoshun Nan, Guoqing Luo, Sicong Leng, Yao Xiao, Wei Lu 发布时间与更新时间:2021.09.11 主题:自然语言处理、关系抽取、对话场景、跨语句、DialogRE、GCN arXiv:…...

周易算卦流程c++实现

代码 #include<iostream> using namespace std; #include<vector> #include<cstdlib> #include<ctime> #include<Windows.h>int huaYiXiangLiang(int all, int& left) {Sleep(3000);srand(time(0));left rand() % all 1;while (true) {if…...

软件架构设计(十三) 构件与中间件技术

中间件的定义 其实中间件是属于构件的一种。是一种独立的系统软件或服务程序,可以帮助分布式应用软件在不同技术之间共享资源。 我们把它定性为一类系统软件,比如我们常说的消息中间件,数据库中间件等等都是中间件的一种体现。一般情况都是给应用系统提供服务,而不是直接…...

PyTorch深度学习实战——基于ResNet模型实现猫狗分类

PyTorch深度学习实战——基于ResNet模型实现猫狗分类 0. 前言1. ResNet 架构2. 基于预训练 ResNet 模型实现猫狗分类相关链接 0. 前言 从 VGG11 到 VGG19&#xff0c;不同之处仅在于网络层数&#xff0c;一般来说&#xff0c;神经网络越深&#xff0c;它的准确率就越高。但并非…...

机器学习第六课--朴素贝叶斯

朴素贝叶斯广泛地应用在文本分类任务中&#xff0c;其中最为经典的场景为垃圾文本分类(如垃圾邮件分类:给定一个邮件&#xff0c;把它自动分类为垃圾或者正常邮件)。这个任务本身是属于文本分析任务&#xff0c;因为对应的数据均为文本类型&#xff0c;所以对于此类任务我们首先…...

基于Java+SpringBoot+Vue的图书借还小程序的设计与实现(亮点:多角色、点赞评论、借书还书、在线支付)

图书借还管理小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1 小…...

【校招VIP】前端计算机网络之UDP相关

考点介绍 UDP是一个简单的面向消息的传输层协议&#xff0c;尽管UDP提供标头和有效负载的完整性验证&#xff08;通过校验和&#xff09;&#xff0c;但它不保证向上层协议提供消息传递&#xff0c;并且UDP层在发送后不会保留UDP 消息的状态。因此&#xff0c;UDP有时被称为不可…...

前缀和实例4(和可被k整除的子数组)

题目&#xff1a; 给定一个整数数组 nums 和一个整数 k &#xff0c;返回其中元素之和可被 k 整除的&#xff08;连续、非空&#xff09; 子数组 的数目。 子数组 是数组的 连续 部分。 示例 1&#xff1a; 输入&#xff1a;nums [4,5,0,-2,-3,1], k 5 输出&#xff1a;7 …...

Android获取系统读取权限

第一步在Androidifest.xml文件中加上授权语句 <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/>并且在Application标签下添加 androi…...

输入学生成绩(最多不超过40),输入为负值时表示输入结束,统计成绩高于平均成绩的学生人数

#include<stdio.h> #define N 40 int scanfscore(int score[N]) {int i -1;do {i;printf("输入学生成绩:");scanf("%d", &score[i]);} while (score[i] > 0);return i; } int average(int score[N], int n) {int j 0;int k 0;double sum …...

【力扣周赛】第 363 场周赛(完全平方数和质因数分解)

文章目录 竞赛链接Q1&#xff1a;100031. 计算 K 置位下标对应元素的和竞赛时代码写法2——手写二进制中1的数量 Q2&#xff1a;100040. 让所有学生保持开心的分组方法数&#xff08;排序后枚举分界&#xff09;竞赛时代码 Q3&#xff1a;100033. 最大合金数&#xff08;二分答…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...