• 关于如何惟一地标识一台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次方之一,自己去算概率!!!

  • 相关阅读:
    Docker学习笔记(一)——安装
    Mac安装Nginx
    Spring Boot学习笔记(二)——HelloWorld实现
    Spring Boot学习笔记(一)——Eclipse安装STS插件
    Redis学习笔记(九)——集群
    Redis学习笔记(八)——持久化
    Redis学习笔记(七)——数据结构之有序集合(sorted set)
    Redis学习笔记(六)——数据结构之Set
    Redis学习笔记(五)——数据结构之哈希(Hash)
    Redis学习笔记(四)——数据结构之List
  • 原文地址:https://www.cnblogs.com/littlepanpc/p/4198604.html
Copyright © 2020-2023  润新知