AndroidID、IMEI、OAID获取

2023-05-16

前言

因为项目中经常会遇到要上传一系列设备信息的功能,为了方便使用,所以就拆分成以下系列文章来单独介绍如何获取各类设备信息

  • 手机运营商获取

  • AndroidID、IMEI、OAID获取

  • 地理位置信息经纬度获取

  • 公网IP地址获取:移动网络IP、Wifi IP

  • Build类获取相关设备信息

  • 屏幕相关信息:密度、物理尺寸获取

  • BuildConfig获取的一系列基础信息

  • UA、网络状态…等持续更新

1. AndroidID获取

1.1 所需权限

不需要任何权限

1.2 获取方法

private fun getAndroidID() {
    val androidID = Settings.System.getString(
        contentResolver, Settings.Secure.ANDROID_ID
    )
    Log.i(TAG, "AndroidID为:$androidID")
}

注意:手机在恢复出厂设置后,这个AndroidID会发生改变,所以用它作为设备的唯一标识不太保险

2. IMEI、MEID获取

2.1 概念了解

讲具体的获取方法前,先大概了解下这是什么东西。

IMEI和MEID其实都是用来标识设备的识别码,不同的是IMEI标识的是支持GSM网络制式的设备MEID标识的是支持CDMA网络制式的设备

什么是GSM和CDMA呢? CDMA和GSM简单点说其实就是使用了不同的通信技术,以下表格显示了各大运营商所使用的通信技术

2G3G4G
中国移动GSMTD-SCDMATD-LTE
中国联通GSMWCDMATD-LTE/FDD-LTE
中国电信CDMA1X 有时直接写CDMACDMA2000 EVDO是中国电信的CDMA2000的3G网络的无线上网模式TD-LTE/FDD-LTE

而现在我们的手机大都是双卡双待,所以这些手机IMEI和MEID号码都有。

大白话讲其实IMEI、MEID就相当于我们手机的身份证号码,唯一标识它,不同的是,有的手机双卡双待,可以同时插入两张支持GSM网络的卡(移动联通、移动移动、联通联通),或一张支持GSM网络的卡一张支持CDMA网络的卡,所以就出现一部手机有两个IMEI号,一个MEID号码

注意:IMEI和MEID是标识手机设备,跟我们手机插什么卡没有关系。

2.2 通过getDeviceId()获取

2.2.1 所需权限

需要动态申请READ_PHONE_STATE权限

注意:Android10以上禁止获取IMEI,因为需要READ_PRIVILEGED_PHONE_STATE权限,而该权限只能是系统应用才可以获取到。

2.2.2 获取方法

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
    val telManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val IMEI = telManager.deviceId
    Log.i(TAG, "IMEI为:${IMEI}")
} else {
    Log.i(TAG, "Android10及以上版本禁止获取IMEI")
}

2.2.3 方法解释

从2.2.2可以看到,我们主要是通过TelephonyManager的getDeviceId()方法来获取的

我们来看看该方法的注解:

/**
    * Returns the unique device ID, for example, the IMEI for GSM and the MEID
    * or ESN for CDMA phones. Return null if device ID is not available.
*
    * <p>Starting with API level 29, persistent device identifiers are guarded behind additional
    * restrictions, and apps are recommended to use resettable identifiers (see <a
    * href="c"> Best practices for unique identifiers</a>). This method can be invoked if one of
    * the following requirements is met:
    * <ul>
    *     <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
    *     is a privileged permission that can only be granted to apps preloaded on the device.
    *     <li>If the calling app is the device or profile owner and has been granted the
    *     {@link Manifest.permission#READ_PHONE_STATE} permission. The profile owner is an app that
    *     owns a managed profile on the device; for more details see <a
    *     href="https://developer.android.com/work/managed-profiles">Work profiles</a>.
    *     Profile owner access is deprecated and will be removed in a future release.
    *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}) on any
    *     active subscription.
    *     <li>If the calling app is the default SMS role holder (see {@link
    *     RoleManager#isRoleHeld(String)}).
    * </ul>
*
    * <p>If the calling app does not meet one of these requirements then this method will behave
    * as follows:
*
    * <ul>
    *     <li>If the calling app's target SDK is API level 28 or lower and the app has the
    *     READ_PHONE_STATE permission then null is returned.</li>
    *     <li>If the calling app's target SDK is API level 28 or lower and the app does not have
    *     the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
    *     higher, then a SecurityException is thrown.</li>
    * </ul>
*
    * @deprecated Use {@link #getImei} which returns IMEI for GSM or {@link #getMeid} which returns
    * MEID for CDMA.
*/
翻译:
返回唯一的设备 ID,例如,GSM 手机的 IMEI 和 CDMA 手机的 MEID 或 ESN。 如果设备ID不可用,则返回 null。 

从Android10 API29开始,就不允许调用该方法,建议使用可重置的标志符,如果满足以下条件,可调用此方法
1、授予了READ_PRIVILEGED_PHONE_STATE该权限,但是该权限仅系统应用才可获得
2、如果应用的API为28或者更低,且具备READ_PHONE_STATE权限,则返回null
3、如果应用API为29或者更高,则会抛出SecurityException异常

建议我们通过getImei方法获取GSM手机的IMEI或者getMeid()方法获取CDMA手机的MEID

总结:

  • 可以看出该方法得到的并不一定是IMEI

  • 对于只有GSM制式的手机是得到的是IMEI,对于只有CDMA制式的手机,返回的是ESN或MEID。

  • 所以对于我们的双卡双待手机,有可能返回IMEI,也有可能返回MEID。这里推荐我们使用getImei()来获取GSM网络制式的IMEI或者getMeid()方法来获取CDMA网络制式的MEID。

2.3 通过getImei()和getMeid()获取

2.3.1 所需权限

需要动态申请READ_PHONE_STATE权限

注意:Android10以上禁止获取IMEI,因为需要READ_PRIVILEGED_PHONE_STATE权限,而该权限只能是系统应用才可以获取到。

2.3.2 获取方法

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q &&Build.VERSION.SDK_INT>Build.VERSION_CODES.O){
    val telManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val imei1 = telManager.getImei(0)
    val imei2 = telManager.getImei(1)
    Log.i(TAG, "IMEI卡槽1:$imei1")
    Log.i(TAG, "IMEI卡槽2:$imei2")

    val meid1 = telManager.getMeid(0)
    val meid2 = telManager.getMeid(1)
    Log.i(TAG, "MEID卡槽1为: $meid1")
    Log.i(TAG, "MEID卡槽2为:$meid2 ")
}

2.3.3 特殊说明

在写文章之前,看到网上关于获取IMEI的文章都是见getDeviceId()获取不到就一股脑的反射调用getImei(),我当时还在想人家这方法本身就能直接调用,你还反射个锤子。

反射是调用@hide标识的class或者是一些方法没有编到SDK里的,也就是我们的隐藏接口,这些才用到反射。后来通过查看5.1、7.1、8、9的源码发现,到7.1,该方法还是隐藏的,从8.0开始,getImei()方法就可以直接调用了,所以傻孩子别再不看版本就一股脑反射调用了。

5.1
在这里插入图片描述

10.0
在这里插入图片描述

2.4 测试结果-总结

通过云端的测试机测试,小米9SE和OPPOR15的数据如下:

小米9SE
IMEI手机卡1:862427041314834
IMEI手机卡2:862427041314842
MEID1为: 99001279065741
MEID2为:	99001279065741 
deviceId为:862427041314834
OPPOR15
IMEI手机卡1:865741048560315
IMEI手机卡2:865741048560307
MEID1为: A0000088576EC0
MEID2为:	A0000088576EC0 
deviceId为:A0000088576EC0

⭐从数据再次验证了2.2和2.3中的说法

  • getDeviceId()返回的不一定是IMEI,也有可能是MEID

  • 一个双卡双待的手机一般IMEI号码有两个,MEID号码有一个

  • 如果想准确的获取手机的IMEI,就使用getImei()方法

3. OAID获取

在2中说道,在Android10以上,安卓是禁止我们获取IMEI的,上面的方法都无法获取到,那如果想要唯一标识一部手机,那我们可以使用OAID

因传统的移动终端设备标识如国际移动设备识别码(IMEI)等已被部分国家认定为用户隐私的一部分,并存在被篡改和冒用的风险,所以在Android 10及后续版本中非厂商系统应用将无法获取IMEI、MAC等设备信息。无法获取IMEI会在用户行为统计过程中对设备识别产生一定影响。

近日移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案,选择OAID字段作为IMEI等的替代字段。OAID字段是由中国信通院联合华为、小米、OPPO、VIVO等厂商共同推出的设备识别字段,具有一定的权威性,可满足用户行为统计的使用场景。

3.1 所需权限

不需要任何权限

3.2 获取方法

3.2.1 下载aar文件

移动安全联盟MSA (msa-alliance.cn) 官网下载如下文件,但是需要登录,注册的账号还需要公司信息等…晕死,嫌麻烦的在该项目Github上自取

在这里插入图片描述

该lib仅支持以下设备获取OAID

在这里插入图片描述

3.2.2 添加依赖

将aar文件添加到lib中,并添加依赖

implementation files('libs/oaid_sdk_1.0.25.aar')

3.2.3 设置gradle编译选项

defaultConfig{
    ndk {
            //设置支持的SO库架构
            abiFilters  'armeabi-v7a', 'arm64-v8a','x86','x86_64','armeabi'
        }
}

3.2.4 assets目录添加supplierconfig.json文件

{
  "supplier":{
    "vivo":{
    },
    "xiaomi": {
    },
    "huawei":{
    },
    "oppo":{
    }
  }
}

注意:一定要添加该文件,否则会报加载配置文件出错

3.2.5 代码实现

class OAIDActivity : AppCompatActivity(), IIdentifierListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_o_a_i_d)

        getOAID()
    }

    private fun getOAID() {
        //初始化
        var error = MdidSdkHelper.InitSdk(this, true, this)
        when (error) {
            ErrorCode.INIT_ERROR_DEVICE_NOSUPPORT -> {
                //不支持的设备
                Log.i(TAG, "getOAID: 不支持的设备")
            }
            ErrorCode.INIT_ERROR_LOAD_CONFIGFILE -> {
                //加载配置文件出错
                Log.i(TAG, "getOAID: 加载配置文件出错")
            }
            ErrorCode.INIT_ERROR_MANUFACTURER_NOSUPPORT -> {
                //不支持的设备厂商
                Log.i(TAG, "getOAID: 不支持的设备厂商")
            }
            ErrorCode.INIT_ERROR_RESULT_DELAY -> {
                //获取接口是异步的,结果会在回调中返回,回调执行的回调可能在工作线程
             Log.i(TAG, "getOAID: 获取接口是异步的,结果会在回调中返回,回调执行的回调可能在工作线程")
            }
            ErrorCode.INIT_HELPER_CALL_ERROR -> {
                //反射调用出错
                Log.i(TAG, "getOAID: 反射调用出错")
            }
        }
    }


    //注意,该回调方法在非主线程中
    override fun OnSupport(isSupport: Boolean, _supplier: IdSupplier?) {

        if (_supplier == null) {
            runOnUiThread {
                tvInfo.text = "获取到的配置信息为空"
            }
            Log.i(TAG, "OnSupport: 获取到的信息为空")
            return
        }
        //关键用这个
        val oaid: String = _supplier.oaid
        val vaid: String = _supplier.vaid
        val aaid: String = _supplier.aaid
        val builder = StringBuilder()               
    }
}

注意:OnSupport()回调方法在非主线程中

4. 总结

  • AndroidID能够直接获取,不需要权限

  • IMEI和MEID只与设备有关,getDeviceId()返回的不一定是IMEI,也有可能是MEID

  • 一个双卡双待的手机一般IMEI号码有两个,MEID号码有一个

  • 如果想准确的获取手机的IMEI,就使用getImei()方法

  • Android10以上无法获取IMEI,可通过获取OAID来作为设备唯一码

在第一次查询如何获取IMEI的相关文章时,真是惊呆我了,有的文章竟然在区分插入移动联通卡和插入电信卡获取方法的区别,拜托,IMEI是跟设备相关的,跟你插什么卡有半毛线关系!!!还有的毛线不看,直接照抄前几年的代码,各种反射来获取,拜托,都可以直接获取了好不好,看不惯那些,所以总结了这篇文章。

项目地址

如果本文对你有帮助,请别忘记点赞start,如果有不恰当的地方也请提出来,下篇文章见。
觉得不错还望老板打个赏呗,帮我买条秋裤穿 (*꒦ິ⌓꒦ີ)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AndroidID、IMEI、OAID获取 的相关文章

  • Android11 授权应用获取IMEI号和ICCID

    在Android11上获取IMEI号等设备信息需要android permission READ PRIVILEGED PHONE STATE权限 xff0c 而这个权限又只授予系统级应用 项目中如果targetSdkVersion值小于2
  • Android 抛弃IMEI改用ANDROID_ID

    介绍 之前一直使用IMEI作为唯一标识符 xff0c 缺点就是需要权限 xff1a Android 10以前 xff0c 需要READ PHONE STATE权限 Android 10限制 xff0c 需要READ PRIVILEGED P
  • 中兴BA510(中国移动定制机)进工程模式恢复IMEI

    1 拨号盘输入 3646633 再拨号 xff0c 或者 3646633 xff0c 进入工程模式 2 找到RADIO information xff1a phone 1输入 AT 43 EMGR 61 1 7 34 IMEI号码1 34
  • Android android_id, deviceId, oaid的区别

    一 ANDROID ID 1 ANDROID ID是设备首次启动时由系统随机生成的一串64位的十六进制数字 2 获取方式 String ANDROID ID span class token operator 61 span Setting
  • Android设备唯一标识(AndroidID,OAID等 )

    一 ID 体系 xff1a 你只是一串代码 想要了解 OAID xff0c 我们首先需要明白 ID 体系 xff1a 想要追踪一个用户就必须先找到用户 xff0c 在这个过程中 xff0c 标识符 xff08 ID xff09 就像我们的另
  • Android获取OAID

    目录 写在最前面 写在前面 说明文档 SDK使用过程 xff1a 代码实现 写在最前面 看评论有好些朋友遇到了一些我没遇到的问题 xff0c 而且看官方文档也已经更新 xff0c 想着这些问题官方是不是已经优化解决了 xff0c 就按着最新
  • Android Q(10.0)上IMEI获取不到;Android Q(10.0)上OAID替代IMEI;OAID获取方式

    最近公司研发的 Android Q xff08 android 10 xff09 的5G手机 xff0c 然后就开始适配Android Q xff1b 发现无系统权限的应用无法获取到可作为唯一标识的IMEI MAC等等 xff1b 由于项目
  • AndroidID、IMEI、OAID获取

    前言 因为项目中经常会遇到要上传一系列设备信息的功能 xff0c 为了方便使用 xff0c 所以就拆分成以下系列文章来单独介绍如何获取各类设备信息 手机运营商获取 AndroidID IMEI OAID获取 地理位置信息经纬度获取 公网IP
  • 什么是手机的IMEI?

    一 xff0c IMEI是什么 xff1f IMEI xff08 International Mobile Equipment Identity xff09 是移动设备国际身份码的缩写 是由15位数字组成的 电子串号 xff0c 该码是全球
  • 如何查明Android设备是否有蜂窝无线电模块?

    我如何确定该设备确实具有 gsm cdma 或其他蜂窝网络设备 不仅仅是 WiFi 我不想检查当前连接的网络状态 因为设备此时可能处于离线状态 我不想通过 TelephonyManager act getSystemService Cont
  • 获取 Android 设备的永久唯一 ID

    我有一个应用程序 我想在其中使用唯一 ID 来识别设备 我尝试了多种解决方案 但在手机重置后唯一 ID 发生了变化 如 ANDROID ID 我使用了下面的 StackOverflow 链接 但现在不可用 Android 设备有唯一的 ID
  • 如何以编程方式在 Windows 8.1 手机中查找 IMEI 号码?

    我正在尝试以编程方式在 Windows Phone 8 1 应用程序中查找 IMEI 号码 并且我引用了许多链接 但找不到任何明确的内容 我无法找到 Windows 8 1 手机应用程序的 Tapi dll 所以 Tapi 库有其他选择吗
  • 如何在android中以编程方式获取设备的IMEI/ESN?

    为了唯一地标识每个设备 我想使用 IMEI 或 CDMA 设备的 ESN 号 如何以编程方式访问它 你想打电话android telephony TelephonyManager getDeviceId 这将返回唯一标识设备的任何字符串 G
  • 如何获取J2ME支持的所有设备的IMEI? [复制]

    这个问题在这里已经有答案了 可能的重复 J2me中如何动态获取手机IMEI号 有没有办法获得 J2ME 支持的所有设备的 IMEI 我做了一些谷歌搜索并找到了下面的解决方案 但它是针对特定设备的 诺基亚 System getProperty
  • android 在 ndk/JNI 的 cc/c++ 中获取 IMEI

    我会尝试得到imei使用 C C 使用 ndk 获取设备的数据并使用 JNI 检索结果 const char res exec get out service call iphonesubinfo 3 在 shell 中工作 但在我的应用程
  • Android 10 中的 Android 开发者无 IMEI

    由于 Android 非常重视安全性 并试图让新的 Android 版本更加安全 因此开发人员很难跟上新的安全功能并找到旧方法的替代方案来使他们的应用程序与旧功能兼容 这个问题是关于新Android 10中的IMEI 旧方法通过使用以下代码
  • Android 10 版本之后如何验证 IMEI 号码?

    我需要验证 IMEI 号码 他们有验证输入 IMEI 的机制吗 我们可以获得 true 或 false 的验证状态吗 您不能 第三方应用程序不能使用 IMEI 也不能使用手机的序列号和其他不可重置的设备标识符 对不可重置设备标识符的限制 从
  • UDID 或 IMEI——哪个更好?

    在开发需要我唯一识别电话用户的应用程序时 我希望得到一些关于最好使用手机的 UDID 还是 IMEI 的建议 使用两者有什么优点 缺点吗 所有评论将不胜感激 ANDROID ID 的优点 设置 安全 ANDROID ID 这是设备首次启动时
  • TelephonyManager.getDeviceId(0) 返回不同的结果

    由于某些特定原因 我需要在 Android 应用程序中的某个时刻获取 IMEI 这是我使用的代码 TelephonyManager tm TelephonyManager getSystemService Context TELEPHONY
  • Android 10:IMEI 在 API 29 上不再可用。寻找替代方案

    我们客户的应用程序的主要功能很大程度上依赖于跟踪客户的设备 他们提供与特定手机 而不是其所有者 绑定的产品 使用设备 IMEI 可以实现这一点 但随着 Android 10 中的隐私更改 他们使其无法访问 https developer a

随机推荐

  • 差分约束 解决区间选点问题

    题意 xff1a 给定一个数轴上的 n 个区间 xff0c 要求在数轴上选取最少的点使得第 i 个区间 ai bi 里至少有 ci 个点 input 输入第一行一个整数 n 表示区间的个数 xff0c 接下来的 n 行 xff0c 每一行两
  • 【已解决】Microsoft Visual C++ Redistributable is not installed

    Error 导入torch xff0c 提示报错 xff1a Microsoft Visual C 43 43 Redistributable is not installed this may lead to the DLL load f
  • 设置让Windows每天在指定时间自动关机

    其实我们的电脑是可以设置每天在指定的时间点自动关机的 xff0c 具体操作方法 xff1a 1 开打电脑 xff0c 点击电脑系统左下角windows图标 xff0c 选择 控制面板 并进入 xff1b 如图 2 在控制面板界面找到 管理工
  • 在 AlmaLinux 9安装Docker Compose

    首先先安装Docker 如何在 AlmaLinux 8 上安装和使用 Docker 检查Docker版本 docker version 安装Docker Compose sudo curl L 34 https github com doc
  • 使用python搭建一个简单的FTP服务器

    从配置文件获取访问FTP服务器目录的用户名 密码 span class token keyword from span pyftpdlib span class token punctuation span authorizers span
  • 更改win10系统C:\Users\中文用户名为英文用户名

    文章目录 前言一 打开注册表二 查找路径三 重启电脑四 将用中文名与英文名进行链接五 测试是否成功 前言 注意 xff1a 做之前请先浏览一遍 xff0c 做任何操作之前都建议不要直接就做 xff0c 先看一看文档中有哪些操作点是需要小心的
  • Cityscapes数据集的深度完整解析

    cityscapes数据集是分割模型训练时比较常用的一个数据集 xff0c 他还可以用来训练GAN网络生成街景图片 数据集下载和文件夹组成 xff1a 整个数据集包含50个欧洲城市 xff0c 5000张精细标注图像 标注位于gtFine文
  • 使用分支——处理Git merge 冲突

    使用分支 处理Git merge 冲突 版本控制系统就是负责管理来自于多个提交者 xff08 通常是开发者 xff09 之间的提交的 有时候多个开发者可能会编辑同一部分内容 一旦开发者A编辑了开发者B正在编辑的内容 xff0c 冲突就会产生
  • 纯手工解密几大在线js加密网站(1)

    0x0 开头 最近闲来无事 xff0c 来看一下目前网络上哪家加密工具的强度最高的 本人技术有限 xff0c 最终结果不能代表什么 xff0c 大家有遇到什么其他的js加密技术破解难题的 xff0c 也可以一起互相讨论 xff0c 也可以问
  • 纯手工解密几大在线js加密网站(3)

    0x0 开头 续接上章 xff0c 心血来潮想挨个破解一下各大js加密的网站 xff0c 了解一下现有的js加密的逻辑 0x1 介绍 Sojson支持js的不可逆混淆加密 xff0c 和很多高级的加密配置 xff0c 还增加了小白专用的一键
  • 如何在局域网内设置多个网段

    连接状态中的 属性 按钮 xff0c 选择 TCP IPv4 协议 xff0c 点击下面的 属性 按钮 xff0c 点击 高级 按钮 在高级TCP IP设置里面点击 添加 按钮 输入新网段的ip地址 xff08 以192网段为例 xff09
  • B-猫猫向前冲(拓扑排序

    题意 xff1a input 输入有若干组 xff0c 每组中的第一行为二个数N xff08 1 lt 61 N lt 61 500 xff09 xff0c M xff1b 其中N表示猫猫的个数 xff0c M表示接着有M行的输入数据 接下
  • 配置wsl2的图形界面

    1 更新源 span class token function sudo span span class token function apt get span update span class token function sudo s
  • 关于yyyyMMdd的正则表达式的使用

    String pattern 61 34 0 9 3 1 9 0 9 2 1 9 0 9 1 0 9 1 1 9 0 9 2 1 9 0 9 3 34 43 34 0 13578 1 02 0 1 9 12 0 9 3 01 0 469 1
  • qt下使用opencascade源代码

    c 43 43 基础太弱 xff0c 纠正一下 xff0c 在PRO中使用包含目录就可以使用 lt gt xff0c 将下载的opencascade文件通过make编译和安装 xff0c 添加引用就可以了 如果你依然对以下没用的操作感兴趣
  • Linux系统下CPU频率的调整

    省电 or 流畅 root 64 android sys devices system cpu cpu0 cpufreq cat scaling available governors hotplug conservative ondema
  • 禁止显示Apache目录列表-Indexes FollowSymLinks

    第一种方法 禁止显示Apache目录列表 Indexes FollowSymLinks 如何修改目录的配置以禁止显示 Apache 目录列表 缺省情况下如果你在浏览器输入地址 xff1a http localhost 8080 如果你的文件
  • 第十一章、远程联机服务器SSH / XDMCP / VNC / RDP

    维护网络服务器最简单的方式不是跑去实体服务器前面登入 xff0c 而是透过远程联机服务器联机功能来登入主机 xff0c 然后再来进行其他有的没的维护就是了 Linux 主机几乎都会提供 sshd 这个联机服务 xff0c 而且这个服务还是主
  • 如何查看电脑jdk/jre版本以及安装路径

    一 按快捷键win 43 r打开运行窗口 二 输入cmd 回车 xff0c 打开命令框 三 输入 java version 查看jdk版本 注意 xff1a java后面需要有空格 xff0c 不然会报错 java span class t
  • AndroidID、IMEI、OAID获取

    前言 因为项目中经常会遇到要上传一系列设备信息的功能 xff0c 为了方便使用 xff0c 所以就拆分成以下系列文章来单独介绍如何获取各类设备信息 手机运营商获取 AndroidID IMEI OAID获取 地理位置信息经纬度获取 公网IP