【android】关于如何惟一地标识一台Android设备的总结性讨论

2024-06-09 22:48

本文主要是介绍【android】关于如何惟一地标识一台Android设备的总结性讨论,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

想必大家在开发Android项目的时候,多多少少会遇到“如何惟一地标识一台Android设备”等类似的问题。不只是以前,即使是现在乃至可以预见的将来,这个问题都将一直存在。

如果大家使用搜索工具搜索的话,大家也能够找到很多的解决方案,但每种方式都多多少少有些缺陷。

我在这里呢,将向大家解释一下诸多常见方案的不足之处,以及推荐一种相对而言比较靠谱的方法。

首先先要说明一下Android设备的情况。我们大家都知道,在起初的时候,Android设备仅仅意味着是“手机”。如果情况一直是这样就好了。可是事实并不是这样的,我们知道,随着Google以及Android的发展壮大,Android系统在除了支持手机之外,也开始向其它领域发展。截止到Android 5.0的时候,Android系统已经能够支持诸如手持设备、可穿戴设备等,详细来说就是已经支持手机、平板、手表、眼镜、电视、盒子以及汽车。所有的这些情况将影响各个解决方案的实际效果。

好,下面我们来一一揭开各个解决方案不足之处的神秘面纱。

ANDROID_ID

ANDROID_ID存在于android.provider.Settings.Secure.ANDROID_ID.它可以通过下面的方式获取得到:

1 String android_id = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID);
View Code

这一个64位的16进制字符串。它在设备首次启动时被创建并存储起来。但是在设备恢复出厂设置或者刷机之时,将不得存在,只能在再次启动时重新生成。这是它的劣势之一。然后,还有,在2.2之前,这种方式并不是百分百可靠的。其次,在主要手持设备生产商生产的流行设备中,还有一个可以被显著观测到的bug,那就是诸多设备拥有相同的ANDROID_ID。所以,ANDROID_ID并不是一个完美的解决方案。

DEVICEID

DEVICEID,顾名思义,“设备id”。是由手机运营商添加进手机中的。它可以通过以下方式获取到:

1 TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
2 String tmDevice = "" + tm.getDeviceId();
View Code

它的返回值将依据运营商的不同,可能返回手机的IMEI或MEID或ESN。由于它是手机运营商添加进去的,所以可能存在收下诸多问题:

非手机:对于不能打电话的平板、智能手表、电视甚至汽车等非手机设备,并不存在这种惟一的标识符。

持续性问题:在拥有DEVICEID的设备上,在经过刷机或者工厂设置后,这个值有可能没有被清理干净。如果是这种情况,我们可能将它们认为是同一设备。

优先级问题:想要获取deviceid需要READ_PHONE_STATE权限。如果你在应用中并未使用到电话,使用这个权限将会很令人不安。 

已知Bug问题:这种方式的实现在有些机器上是有bug的,会返回一些垃圾信息,比如0或者"*".

所以,DEVICEID也不能完美的解决这个问题。

SIMSERIALNUMBER

SimSerialNumber也是由手机运营商放进去的,它的获取方式是这样的:

1 TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
2 String tmSerial = "" + tm.getSimSerialNumber();
View Code

它的不靠谱之处也尤如DeviceId。

SERIALNUMBER

它是2.3之后才引入的。它的值存在于android.os.Build.SERIAL.SerialNumber。但是对于不支持通话的设备,得先需要唯一的deviceid。

Mac地址

也许有人可能想到依据设备的WiFi或者蓝牙硬件来获取Mac地址来惟一标识设备。但是这种方式是不值得推荐的。因为它并非问题可以获取得到的,因为它需要设备WiFi或者蓝牙开着。所以,如果设备不打开蓝牙呢?如果设备没有打开WiFi而是使用的2G、3G或者4G呢?所以这也是一个不靠谱的方式。

UUID

以上几种标识Android设备的方式都不尽如人意思。难道就没有一种方式可以稳定、可靠且唯一地标识Androi硬件设备的吗?

诶,等一等,标识Android设备非得使用设备的硬件信息吗?难得使用非硬件就不能标识设备了吗?

好吧,答案是UUID。UUID(Universal Unique ID)是软件界的“通用唯一ID”, 是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字

UUID由以下几部分的组合:

  1. 当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
  2. 时钟序列。
  3. 全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。

UUID的唯一缺陷在于生成的结果串会比较长。关于UUID这个标准使用最普遍的是微软的GUID(Globals Unique Identifiers)。在ColdFusion中可以用CreateUUID()函数很简单地生成UUID,其格式为:xxxxxxxx-xxxx- xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每个 x 是 0-9 或 a-f 范围内的一个十六进制的数字。而标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx (8-4-4-4-12),可以从cflib 下载CreateGUID() UDF进行转换。

对于一个开发人员而言,想要追踪应用的每一次安装,是非常普遍,也十分合乎情理的。 要追踪应用的安装,你可以使用 UUID 来作为标识,在安装之后应用首次运行之时创建它。下面是一个叫作“ Intallation ”的类,带有一个静态方法id(Context context),返回应用的UUID 。你可以将更多有关安装的数据写入”ISTALLATION”文件中。

 1 public class Installation {
 2     private static String sID = null;
 3     private static final String INSTALLATION = "INSTALLATION";
 4 
 5     public synchronized static String id(Context context) {
 6         if (sID == null) {  
 7             File installation = new File(context.getFilesDir(), INSTALLATION);
 8             try {
 9                 if (!installation.exists())
10                     writeInstallationFile(installation);
11                 sID = readInstallationFile(installation);
12             } catch (Exception e) {
13                 throw new RuntimeException(e);
14             }
15         }
16         return sID;
17     }
18 
19     private static String readInstallationFile(File installation) throws IOException {
20         RandomAccessFile f = new RandomAccessFile(installation, "r");
21         byte[] bytes = new byte[(int) f.length()];
22         f.readFully(bytes);
23         f.close();
24         return new String(bytes);
25     }
26 
27     private static void writeInstallationFile(File installation) throws IOException {
28         FileOutputStream out = new FileOutputStream(installation);
29         String id = UUID.randomUUID().toString();
30         out.write(id.getBytes());
31         out.close();
32     }
33 }
Installation.java

它是通过软件产生的UUId来惟一地标识软件在该设备上的安装来标识这台设备,而非通过硬件信息。当然,这种方式是通过将UUID保存在本地文件中来实现的,如果你清空了本应用数据或者删除了该文件的话,应用将重新生成一个UUID,这也就意味着设备的惟一标识符发生了变化,这是一台新设备。

UUID是一个随机的数值,那么它万一发生了重复值呢?好吧,这是一串32位的十六进制的数字,它产生重复值的概率是16的32次方之一,自己去算概率!!!



转载:http://www.cnblogs.com/littlepanpc/p/4198604.html

这篇关于【android】关于如何惟一地标识一台Android设备的总结性讨论的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1046521

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

如何编写Linux PCIe设备驱动器 之二

如何编写Linux PCIe设备驱动器 之二 功能(capability)集功能(capability)APIs通过pci_bus_read_config完成功能存取功能APIs参数pos常量值PCI功能结构 PCI功能IDMSI功能电源功率管理功能 功能(capability)集 功能(capability)APIs int pcie_capability_read_wo

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

Android逆向(反调,脱壳,过ssl证书脚本)

文章目录 总结 基础Android基础工具 定位关键代码页面activity定位数据包参数定位堆栈追踪 编写反调脱壳好用的脚本过ssl证书校验抓包反调的脚本打印堆栈bilibili反调的脚本 总结 暑假做了两个月的Android逆向,记录一下自己学到的东西。对于app渗透有了一些思路。 这两个月主要做的是代码分析,对于分析完后的持久化等没有学习。主要是如何反编译源码,如何找到