1、方案一IMEI

    IMEI(International Mobile Equipment Identity)是国际移动设备识别码的缩写,由15-17位数字组成,与手机是一一对应的关系,该码是全球唯一的,并且永远不会改变。

2、不同版本获取IEMI的方式

    在Android 8.0(API Level 26)以下,可以通过TelephonyManager的getDeviceId()方法获取到设备的IMEI码(其实这里的说法不准确,该方法是会根据手机设备的制式(GSM或CDMA)返回相应的设备码(IMEI、MEID和ESN)),该方法在Android 8.0及之后的版本已经被废弃了,取而代之的是getImei()方法。获取设备IMEI码的示例代码如下:

   

    无论是getDeviceId()方法还是getImei()方法都可以传入一个参数slotIndex,用于设备中插入了双卡的情况,这里就不展示了。
    IMEI码的获取方式很简单,也能保证唯一性和不变性,目前很多应用都使用IMEI码作为设备的唯一标识,但众所周知,在Android 6.0以上获取IMEI码是需要动态申请READ_PHONE_STATE权限的,一旦用户拒绝了该权限就获取不到了。这还不是最要命的,在Android 10中官方已经明确说明第三方应用无法获取到IMEI码,是因为AndroidQ中去掉了READ_PHONE_STATE权限,取而代之的是一个系统级别的权限:READ_PRIVILEGED_PHONE_STATE,所以Android Q平台无论如何也不会再有IMEI和序列号SerialNumber,详细内容可以查看Android 10 中的隐私权变更。

下面是几种不同情况下IMEI码的获取情况:

Android 6.0以下:无需申请权限,可以通过getDeviceId()方法获取到IMEI码
Android 6.0-Android 8.0:需要申请READ_PHONE_STATE权限,可以通过getDeviceId()方法获取到IMEI码,如果用户拒绝了权限,会抛出java.lang.SecurityException异常
Android 8.0-Android 10:需要申请READ_PHONE_STATE权限,可以通过getImei()方法获取到IMEI码,如果用户拒绝了权限,会抛出java.lang.SecurityException异常
Android 10及以上:分为以下两种情况:
targetSdkVersion<29:没有申请权限的情况,通过getImei()方法获取IMEI码时抛出java.lang.SecurityException异常;申请了权限,可以正常获取IMEI。
targetSdkVersion=29:无论是否申请了权限,通过getImei()方法获取IMEI码时都会直接抛出java.lang.SecurityException异常。

3、方案二ANDROID_ID

    ANDROID_ID是设备的系统首次启动时随机生成的一串字符,由16个16进制数(64位)组成,基本上还是可以保证唯一性的,获取ANDROID_ID的示例代码如下:

String androidId = Settings.System.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

    ANDROID_ID的获取门槛是最低的,不需要任何权限,但ANDROID_ID也存在一些缺点,就是无法保证稳定性,root、刷机或恢复出厂设置都会导致设备的ANDROID_ID发生改变。此外,我看到部分文章中有提到某些厂商定制系统的Bug会导致不同的设备可能会产生相同的ANDROID_ID,而且某些设备获取到的ANDROID_ID为null。如果应用对于设备标识的要求不是特别高的话还是一个值得考虑的方案。

4、方案三Pseudo-Unique ID

    有一些特殊的情况,如平板电脑的设置没有通话功能,或者不愿加入READ_PHONE_STATE许可。而仍然想获得唯一序列号之类的东西。这时可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但出现类似情况的可能性基本可以忽略。要实现这一点,可以使用Build类,大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35”。这样这个ID看起来就和15位IMEI一样了:

 

这个的缺点就是不是百分百唯一。

5、解决方案

    为了获取IMEI,尝试了adb shell的方式、反射方式都不行。

Android 6.0以下:无需申请权限,可以通过getDeviceId()方法获取到IMEI码
Android 6.0以上:我们目前的targetSdkVersion=23,需要申请READ_PHONE_STATE权限,可以通过getDeviceId()、getImei()方法获取到IMEI码,如果用户拒绝了权限,有两个方案:

  1. 拒绝权限后退出应用不让使用,下次继续请求权限直到同意为止,如果用户选择了“拒绝且不再提示”这种情况,只能阻塞住,提示用户手动去应用管理打开权限。
  2. 我们每次传给后台两个id(IMEI和android_id),拒绝权限后IMEI传空串,获取android_id上报给后台,如果特殊机型android_id返回null,需要我们跟后台商量一个特殊的标记,或者可以使用Pseudo-Unique ID;后台可以对IMEI和android_id进行双重校验,通过校验这两个id来判断是否同一个设备。

我们在获取权限之前会弹窗提示禁止权限会影响应用的功能使用,尽量引导他同意权限。

android获取设备唯一ID方法相关推荐

  1. android设备id完美解决方法,安卓获取渠道名渠道id Android获取设备唯一标识的终极解决方法,防止安卓7.0时崩溃问题...

    一,先说获取渠道名(这里以友盟为例) /* * 4.5.1新加渠道名字段,用来传给后台去统计各个渠道下载量 * */ public static String getSource() { //获取渠道 ...

  2. Android Q 获取设备唯一ID(UDID\GUID\UUID\SSAID\GAID)

    Android Q获取设备唯一ID(UDID\GUID\UUID\SSAID\GAID) 一.简介 1.1 问题背景 1.2 关键技术 二.解决方案 2.1 谷歌官方推荐方案 (4种) 2.2 实现方 ...

  3. android 获取蓝牙设备id_获取设备唯一ID的几种方式

    博客摘要:很简单,就是获取设备的唯一ID,直接上正文. 先来看看几种比较单一的方式: IMEI 方式:TelephonyManager.getDeviceId(): 问题 范围:只能支持拥有通话功能的 ...

  4. 获取设备唯一ID的几种方式

    博客摘要:很简单,就是获取设备的唯一ID,直接上正文. 先来看看几种比较单一的方式:  IMEI 方式:TelephonyManager.getDeviceId(): 问题 范围:只能支持拥有通话功能 ...

  5. android获取设备唯一标识完美解决方案

    转自:https://blog.csdn.net/aa1733519509/article/details/50053553 有时需要对用户设备进行标识,所以希望能够得到一个稳定可靠并且唯一的识别码. ...

  6. Android获取设备序列号的方法与调用方式

    记录一下安卓获取设备序列号的方法,以及调用方式 方法: /*** * 使用反射调用系统隐藏方法get(),获取系统相关属性配置* @param key 属性名称* @return*/ static S ...

  7. android获取设备唯一标识_数据埋点:用户唯一标识

    用户唯一标识,是用户唯一的身份ID,相同的身份ID,就会被当做是相同的一个用户. 01 为什么要建设用户唯一标识 如何区分某个用户就是他这个用户,而不是另一个用户,在数据埋点中,是一个非常重要的事情. ...

  8. Android 获取设备唯一标识

    一.背景 项目开发中,多少会遇到这种需求:获得设备唯一标识DeviceId,用于标识一个唯一的设备,做数据精准下发或者数据统计分析. 这类文章,网上有许多资料,例如:使用IMEI.MAC等作为设备标识 ...

  9. Android 10 获取设备唯一id

    android_id是设备的系统首次启动生成的一串字符,基本可以保证唯一性,获取方式: public static String getAndroidID() {     String id = Se ...

最新文章

  1. [DP] LGTB 玩THD (复杂状态DP)
  2. 使用imbalanced-learn处理数据不均衡问题
  3. web project、web service project和java project的区别
  4. 网络篇:朋友面试之TCP/IP,回去等通知吧
  5. Linux查看文件内容的6种命令
  6. leetcode 448. 找到所有数组中消失的数字(Find All Numbers Disappeared in an Array)
  7. python中的counter函数_Python的 counter内置函数,统计文本中的单词数量
  8. Linux常用命令汇总--tree
  9. 基于Bayes和KNN的newsgroup 18828文本分类器的Python实现
  10. api. feel.ai_如何使用Api.ai构建自己的AI助手
  11. 菜鸟教程 linux ubuntu,菜鸟教程 Ubuntu 11.0下搭建Web服务器
  12. python绘制网格地图_「GIS教程」Python-GeoPandas地图、专题地图绘制
  13. Oracle 数据去重sql
  14. (三)feild ii 相控阵聚焦成像:RF信号到成像全过程
  15. 窄带干扰与宽带干扰的模型
  16. 如何建立一套简单又高效的研发管理体系
  17. 攻防世界illusion暴力破解
  18. 如何把文档转成html格式转换,文档格式转换工具Print2Flash使用教程:如何将文档转换为Print2Flash格式件或HTML5文件?...
  19. 打飞机游戏(Appinventor练习)
  20. 我是如何从0开始,在23天里完成一款Android游戏开发的 – Part4~7

热门文章

  1. 关于origin画图的一些小tips
  2. 基于SSM的数码商城的设计与实现【课程设计】
  3. 执行RMAN恢复的高级场景_执行灾难恢复(Disaster Recovery)
  4. Git与远程仓库的连接操作
  5. SpringBoot整合RabbitMQ(包含生产者和消费者)
  6. python url中文传参乱码问题
  7. 从零开始玩域名!窥探互联网财富秘密!
  8. 用c语言怎么查找字符串,c语言如何查找字符串?
  9. [Python教程入门教程]Python五子棋小游戏实例分享
  10. mongodb 备份压缩_MongoDB 备份方法