Android Test3 获取的ANDROID_ID值不同

Android Test3 获取的ANDROID_ID值不同

这篇文章来说明上一篇文章中说到的一个现象:在同一个项目中,创建不同的 app module,运行同一段测试代码,获取到的 ANDROID_ID 的值不同。

我也是第一次认真研究这个现象,这个还涉及到了 ANDROID_ID 值的系统访问的执行原理。这里一起来看下,有知道更详细细节的大佬,不吝在评论里添加。

下面几种场景。

ANDROID_ID 结果差异

下面是几种不同差异的场景。

1. applicationId 不同,ANDROID_ID 不同

在同一个项目目录下,创建两个不同的 app module,会产生不同有 applicationId 值。在新建的 app module 的 src/androidTest 目录下拷贝一份原有 app module 的测试代码。

@RunWith(AndroidJUnit4::class)
class ToolsAndroidTest {companion object {const val SDK_33_ANDROID_ID = "fd8aa7fe27625e8d"  // 正常执行 app 程序读取到 ADNROID_ID}private lateinit var _appContext: Context@Beforefun setup() {_appContext = ApplicationProvider.getApplicationContext<Context>()}@Testfun test_getDeviceId_shouldReturnDeviceId() {val deviceId = Tools.getDeviceId(_appContext)Assert.assertNotEquals(deviceId, "", "Unexpected device id.")Assert.assertEquals(SDK_33_ANDROID_ID, deviceId)}
}

新建的 app module 命名 testsdk,原有的 app module 依然叫 app

两个 module 的区别:

  1. applicationId 值不同:
    • testsdkapplicationId "com.sanren1024.testsdk"
    • appapplicationId "com.sanren1024.phone"
  2. 实现不同:
    • testsdk 仅有测试代码,没有任何的逻辑实现,包括界面设计。
    • app 中有诸多逻辑的实现,包括自定义的 Application 实现,它是一个完整功能的 app 模块。

分别运行 testsdkapp 的测试代码。

  • 运行 testsdk 的测试代码,获取的 deviceId 值是 6fafd019bf9cd426,详细信息如下。

    org.junit.ComparisonFailure: expected:<[fd8aa77327a25e8d]> but was:<[6fafd019bf9cd426]>
    at org.junit.Assert.assertEquals(Assert.java:117)
    at org.junit.Assert.assertEquals(Assert.java:146)
    ...
    
  • 运行 app 的测试代码,获取的 deviceId 值是 fd8aa77327a25e8d.

两者的测试获取的值不同。预期的 testsdk 结果值应该与 app 的执行值一致,而实际 testsdk 执行结果是另一个值。


2. applicationId 不同,ANDROID_ID 相同

再新建一个 app module,命名 testapp,与 testsdk 一样,只包含测试代码。testappapplicationId 值为 "com.sanren1024.phone",这个值与 app 相同。

比较 testsdktestapp 的测试代码结果,testsdk 执行结果是 6fafd019bf9cd426testapp 执行结果是 6fafd019bf9cd426。看出来了,两者的结果值是相同的。


3. applicationId 相同,ANDROID_ID 不同

分别运行 apptestapp,这两个 app module 的 applicationId 相同,查看运行结果。

app 测试代码执行结果 fd8aa77327a25e8dtestapp 测试代码执行结果 6fafd019bf9cd426。两者也不同。

上面三种情况下,导致了我对 ANDROID_ID 值变化的疑惑。


分析差异

上面的几个场景中,只有 app 包含了完整的功能实现,另外两个 app module 都只保含了测试代码。所以重点是排查 app 内相关配置和可能的实现。经过仔细查看后,发现的差异是在 appbuild.gradlebuildType block 中,配置了 debug 这个 build variant 的签名。

android {//...signingConfigs {//...'platform' {storeFile file('../platform.keystore')storePassword '123456'keyAlias 'platform'keyPassword '123456'}}buildTypes {//...debug {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-sqaDebug.pro'signingConfig signingConfigs.'platform'versionNameSuffix ".0"debuggable true}}
}

找到了这个差异,于是将 signingConfig 设置项注释掉,并再次执行测试代码。于是惊喜出现了,得到下面的异常信息。

org.junit.ComparisonFailure: expected:<[fd8aa77327a25e8d]> but was:<[6fafd019bf9cd426]>
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
...

与 场景1 中贴出的错误信息一致。那就猜想一个事实,app 读取的 ANDROID_ID 值与签名有关联。

为了验证猜想,修改 debug block 的 signingConfig 为另一个签名文件。

android {//...signingConfigs {'debug_alter' {storeFile file('../debug_alter.jks')storePassword '123456'keyAlias 'debug_alter'keyPassword '123456'}'platform' {storeFile file('../platform.keystore')storePassword '123456'keyAlias 'platform'keyPassword '123456'}}buildTypes {//...debug {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-sqaDebug.pro'signingConfig signingConfigs.'debug_alter'versionNameSuffix ".0"debuggable true}}
}

执行测试代码后,结果错误信息如下。

org.junit.ComparisonFailure: expected:<[fd8aa77327a25e8d]> but was:<[3e1b82e6762993df]>
at org.junit.Assert.assertEquals(Assert.java:117)
at org.junit.Assert.assertEquals(Assert.java:146)
...

从上面这段输出结果看出,这次执行后的 ADNROID_ID 结果是 3e1b82e6762993df,与开始执行结果不同。这也佐证了上面的猜想。

随机去查看源码:

文件:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerUtils.java:61

frameworks/base/core/java/android/provider/Settings.java

// ActivityManagerUtils.java:56
public class ActivityManagerUtils {// .../*** Return a hash between [0, MAX_VALUE] generated from the android ID.*/@VisibleForTestingstatic int getAndroidIdHash() {// No synchronization is required. Double-initialization is fine here.if (sAndroidIdHash == null) {final ContentResolver resolver = ActivityThread.currentApplication().getContentResolver();// 读取 ANDROID_ID 最直接的调用位置final String androidId = Settings.Secure.getStringForUser(resolver,Settings.Secure.ANDROID_ID,resolver.getUserId());  // 获取当前使用用户idsAndroidIdHash = getUnsignedHashUnCached(sInjectedAndroidId != null ? sInjectedAndroidId : androidId);}return sAndroidIdHash;}// ...
}// Settings.java:6424
public final class Settings {// ...public static final class Secure extends NameValueTable {// ...@UnsupportedAppUsagepublic static String getStringForUser(ContentResolver resolver, String name,int userHandle) {// ...return sNameValueCache.getStringForUser(resolver, name, userHandle);}// ...}// ...private static class NameValueCache {@UnsupportedAppUsagepublic String getStringForUser(ContentResolver cr, String name, final int userHandle) {// ......}}
}

从上面源码调用流程上,它最终调用到 NameValueCache#getStringForUser(ContentResolver, String, final int) 方法,最后的值与系统的 user id 和 当前 app 的信息(签名,ApplicationInfo 等)都有关系。

结论:不同 app 的 apk 在同一台设备上读取到的 ADNROID_ID 基本肯定是不同的。同一个 app 的不同签名的 apk 在同一设备上基本是不同的。(基本不同是因为还与 Android 的系统版本有关系)


结论

造成文章开头说的 ANDROID_ID 值不同的原因是 Android 系统的设计导致的。在版本高些的 Android 系统上,ANDROID_ID 的值与系统版本,应用签名,用户ID都有关系。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/83397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSON 和 LabVIEW Data Types 互相转换

使用JSONtext C:\Program Files (x86)\National Instruments\LabVIEW 2021\examples\JDP Science\JSONtext JSONtext LabVIEW Data Types.vi

docker和docker-compose的版本对应关系怎么看?

docker和docker-compose的版本对应关系怎么看&#xff1f;最近在安装这两个工具&#xff0c;像知道他们的版本对应关系&#xff0c;查了不少资料才找到。 虽然 Docker 和 Docker Compose 的版本并不严格绑定&#xff0c;但是在某些情况下&#xff0c;新版本的 Docker Compose …

邮科ODM摄像头:多维度护航高铁安全系统方案解析

‌高铁作为现代交通的重要支柱&#xff0c;其安全稳定运行依赖于高效的监控体系。摄像头系统作为高铁安全管理的“视觉感知中枢”&#xff0c;凭借多场景覆盖、智能分析以及环境适应性设计&#xff0c;在行车安全、设备维护、乘客服务等方面发挥着不可或缺的作用。本文将从技术…

盒模型小全

CSS盒子模型详解 1. 定义 CSS盒子模型是用于描述HTML元素在页面中布局和表现的核心概念之一。在CSS中&#xff0c;所有HTML元素都被视为一个矩形的盒子&#xff0c;这些盒子封装了周围的HTML元素&#xff0c;并允许在其他元素和周围元素边框之间的空间放置内容。 2. 组成部分…

自定义鼠标效果 - 浏览器扩展使用教程

自定义鼠标效果 - 浏览器扩展使用教程 这里写目录标题 自定义鼠标效果 - 浏览器扩展使用教程功能特点安装方法Chrome/Edge浏览器 使用指南1. 更改鼠标光标样式2. 启用鼠标轨迹效果3. 自定义轨迹效果点状/彩虹/渐隐轨迹&#xff1a;表情轨迹&#xff1a; 管理自定义光标支持的文…

基于SpringBoot实现的课程答疑系统设计与实现【源码+文档】

基于SpringBootVue实现的课程答疑系统采用前后端分离架构方式&#xff0c;系统设计了管理员、学生、老师三种角色&#xff0c;系统实现了用户登录与注册、个人中心、学生管理、老师管理、科目类型管理、学生问题管理、老师回答管理、老师信息管理、关注列表管理、交流区、轮播图…

御微半导体面试总结

前一阵子在公司干的难受&#xff0c;所以再合肥这边面试了几家公司&#xff0c;挑一个御微半导体来说一下吧&#xff0c;公司主要是做半导体晶元测量的&#xff0c;具体啥我也不太明白。 公司产品线多&#xff0c;每条产品线配有独立的软件、结构、光学控制等人员开发语言和框…

Android Compose 自定义圆形取色盘

val Dp.toPx: Floatget() {var scale 3f // MyApplication.context.resources.displayMetrics.apply { // scale density // }return value * scale}val colors List(360) { i ->Color.hsv(360f - i, 1f, 1f) // 360到1的所有HSV颜色 }Preview …

vscode 配置 latex

下载插件 安装插件前自行安装 texlive, 按照 https://tug.org/texlive/ 要求安装 找到 settings 打开 json 文件 在 json 文件中添加如下配置 "latex-workshop.latex.tools": [{"name": "latexmk","command": "latexmk",&qu…

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(质检)

船舶质检管理现状&#xff1a;质检环节部分依赖人工检测&#xff0c;质检员依据质量标准对产品进行抽检或全检。人工质检受质检员主观因素影响较大&#xff0c;不同质检员对标准的把握可能存在差异。 一、痛点与需求 1 Arbigtec 人工经验依赖严重&#xff1a; 质检员的检测准确…

jenkins gerrit-trigger插件配置

插件gerrit-trigger下载好之后要在Manage Jenkins -->Gerrit Trigger-->New Server 中新增Gerrit Servers 配置好保存后点击“状态”查看是否正常

ubuntu24.04下 zookeeper3.8.4 集群的配置

1、环境 1.1 三台机器网络互通&#xff0c;并做hosts解析 准备三台及以上ubuntu24.04主机&#xff08;奇数&#xff09; rootzk-node01:~# hostname zk-node01rootzk-node01:~# cat /etc/hosts 127.0.0.1 localhost 127.0.1.1 u24-server10.0.49.215 zk-node01 10.0.4…

火山引擎 veFuser:面向扩散模型的图像与视频生成推理服务框架

资料来源&#xff1a;火山引擎-开发者社区 DiT 模型与推理挑战 近年来&#xff0c;扩散模型&#xff08;Diffusion Models&#xff09;在生成式人工智能领域取得了突破性进展&#xff0c;尤其是在图像和视频生成方面表现卓越。基于 Transformer 的扩散模型&#xff08;DiT, D…

动态多目标进化算法:VARE(Vector Autoregressive Evolution)求解DF1-DF14,提供完整MATLAB代码

一、VARE简介 VARE&#xff08;Vector Autoregressive Evolution&#xff09;算法是2023年提出的一种新型的动态多目标优化&#xff08;DMO&#xff09;算法&#xff0c;旨在有效处理随时间变化的多目标优化问题。它通过结合向量自回归&#xff08;VAR&#xff09;模型和环境感…

【JavaEE】-- HTTPS

文章目录 1. HTTPS是什么&#xff1f;2. 加密是什么&#xff1f;2.1 引入对称加密&#xff08;效率高&#xff09;2.2 引入非对称加密&#xff08;效率低&#xff09;2.3 引入证书2.3.1 数据签名2.3.2 通过证书解决中间人攻击 1. HTTPS是什么&#xff1f; HTTP也是一个应用层协…

撰写脚本,通过发布/joint_states话题改变机器人在Rviz中的关节角度

撰写脚本&#xff0c;通过发布/joint_states话题改变机器人在Rviz中的关节角度 提问 为我写一个改变关节base_spherical_center_high_joint角度的python脚本吧。适用于ROS2的humble 回答 下面是一个适用于 ROS 2 Humble 的 Python 脚本&#xff0c;它会以指定频率持续发布 …

Redis : Hash类型

哈希类型 哈希类型的命令 hset 设置key指定的字段&#xff08;field&#xff09;的值&#xff08;value&#xff09; 也可以设置多组field和value hget 获得哈希中指定字段的值 如果该字段为空或者key为空则返回nil hexists 判断哈希中是否有该字段的值 如果有则会返回1…

【Chipyard】 conda 环境安装与使用

一、Conda 安装&#xff08;以 Miniconda 为例&#xff09; Conda 是一个强大的环境管理工具&#xff0c;可用于创建、隔离和管理不同的 Python/R 环境。以下是在 Ubuntu 上安装和使用的完整流程&#xff1a; 1. 下载 Miniconda 安装包 bash # 下载最新版 Miniconda3&#…

【愚公系列】《生产线数字化设计与仿真》009-颜色分类站仿真(设置颜色分类站的仿真序列)

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…

ios 26官宣:car play升级提升车载体验

苹果公司正式官宣推出ios 26&#xff0c;该版本为ios 18的后续版本。此次软件更新在命名上焕然一新&#xff0c;设计层面更是实现了全面革新。其中&#xff0c;car play界面迎来全新升级&#xff0c;同时还新增了car play ultra功能。借助这一功能&#xff0c;用户不仅能够使用…