UUID介绍以及android中使用

讨论UUID的定义、分类、应用及生成工具。

什么是UUID?

UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符。UUID具有以下涵义:

  • 经由一定的算法机器生成
为了保证UUID的唯一性,规范定义了包括网卡MAC地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素,以及从这些元素生成UUID的算法。UUID的复杂特性在保证了其唯一性的同时,意味着只能由计算机生成。
  • 非人工指定,非人工识别
UUID是不能人工指定的,除非你冒着UUID重复的风险。UUID的复杂性决定了“一般人“不能直接从一个UUID知道哪个对象和它关联。
  • 在特定的范围内重复的可能性极小
UUID的生成规范定义的算法主要目的就是要保证其唯一性。但这个唯一性是有限的,只在特定的范围内才能得到保证,这和UUID的类型有关(参见UUID的版本)。

UUID是16字节128位长的数字,通常以36字节的字符串表示,示例如下:

3F2504E0-4F89-11D3-9A0C-0305E82C3301

其中的字母是16进制表示,大小写无关。

GUID(Globally Unique Identifier)是UUID的别名;但在实际应用中,GUID通常是指微软实现的UUID。

UUID的版本

UUID具有多个版本,每个版本的算法不同,应用范围也不同。

首先是一个特例--Nil UUID--通常我们不会用到它,它是由全为0的数字组成,如下:

00000000-0000-0000-0000-000000000000

UUID Version 1:基于时间的UUID

基于时间的UUID通过计算当前时间戳、随机数和机器MAC地址得到。由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。

UUID Version 2:DCE安全的UUID

DCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少用到。

UUID Version 3:基于名字的UUID(MD5)

基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。

UUID Version 4:随机UUID

根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但随机的东西就像是买彩票:你指望它发财是不可能的,但狗屎运通常会在不经意中到来。

UUID Version 5:基于名字的UUID(SHA1)

和版本3的UUID算法类似,只是散列值计算使用SHA1( Secure Hash Algorithm 1 )算法。

UUID的应用

从UUID的不同版本可以看出,Version 1/2适合应用于分布式计算环境下,具有高度的唯一性;Version 3/5适合于一定范围内名字唯一,且需要或可能会重复生成UUID的环境下;至于Version 4,我个人的建议是最好不用(虽然它是最简单最方便的)。

通常我们建议使用UUID来标识对象或持久化数据,但以下情况最好不使用UUID:

  • 映射类型的对象。比如只有代码及名称的代码表。
  • 人工维护的非系统生成对象。比如系统中的部分基础数据。
对于具有名称不可重复的自然特性的对象,最好使用Version 3/5的UUID。比如系统中的用户。如果用户的UUID是Version 1的,如果你不小心删除了再重建用户,你会发现人还是那个人,用户已经不是那个用户了。(虽然标记为删除状态也是一种解决方案,但会带来实现上的复杂性。)

UUID生成器

我没想着有人看完了这篇文章就去自己实现一个UUID生成器,所以前面的内容并不涉及算法的细节。下面是一些可用的Java UUID生成器:

  • Java UUID Generator (JUG):开源UUID生成器,LGPL协议,支持MAC地址。
  • UUID:特殊的License,有源码。
  • Java 5以上版本中自带的UUID生成器:好像只能生成Version 3/4的UUID。

此外,Hibernate中也有一个UUID生成器,但是,生成的不是任何一个(规范)版本的UUID,强烈不建议使用。



Android获取本机唯一序列号和可变UUID方法

UUID+设备号序列号 唯一识别码(不可变)

private String getMyUUID(){

  final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);   

  final String tmDevice, tmSerial, tmPhone, androidId;   

  tmDevice = "" + tm.getDeviceId();  

  tmSerial = "" + tm.getSimSerialNumber();   

  androidId = "" +android.provider.Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

  UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());   

  String uniqueId = deviceUuid.toString();

  Log.d("debug","uuid="+uniqueId);

  return uniqueId;

 }

Java 获取可变UUID

 private String getMyUUID(){

  UUID uuid = UUID.randomUUID();

     String uniqueId = uuid.toString();

   Log.d("debug","----->UUID"+uuid);

    return uniqueId;

   }

获得的格式:如下样子

d22f30b8-2716-41d2-84f2-4cd56bb75ecc


### Android 平台上的 UUID 生成及使用方法 #### 基于设备信息生成唯一 UUID 为了在 Android 设备上基于特定硬件属性创建唯一的 `UUID`,可以利用设备 ID 和其他识别码组合来构建。具体实现如下所示: ```java import android.telephony.TelephonyManager; import android.provider.Settings.Secure; public class DeviceUuidFactory { private static final String TAG = "DeviceUuidFactory"; public static UUID getDeviceUuid(TelephonyManager telephonyManager, Context context) { String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); String tmDevice = "" + telephonyManager.getDeviceId(); String tmSerial = "" + telephonyManager.getSimSerialNumber(); // 构建 UUID 对象 UUID deviceUuid = new UUID( androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode() ); return deviceUuid; } } ``` 此代码片段展示了如何通过拼接多个标识符并转换成哈希值的方式构造一个相对稳定的 `UUID`[^1]。 #### 随机生成 V4 版本的 UUID 如果应用程序不需要依赖具体的物理地址或其他持久化特征,则可以选择采用随机算法产生的 v4 类型 `UUID` 来满足需求。下面给出了一种简单的方法用于获取此类形式的身份编码: ```javascript // JavaScript 示例 (Node.js 或浏览器环境) const { v4: uuidv4 } = require('uuid'); let randomUUID = uuidv4(); console.log(randomUUID); // 打印形如 '1b2c3d4e-f5g6-h7i8-j9k0-lmnoprstuvwx' ``` 对于 Java/Android 开发者来说,在不借助第三方库的情况下也可以很容易地做到这一点: ```java String randomUUID = java.util.UUID.randomUUID().toString(); System.out.println(randomUUID); // 同样会打印出类似的字符串表示形式 ``` 这里展示的是标准库函数调用来获得一个新的随机版本四 `UUID` 实例,并将其转化为易于阅读的形式输出[^2]。 #### 创建固定长度的自定义 UUID 字符串 有时可能希望得到具有一定模式或限定大小的结果集作为应用内的唯一键值对。此时可以通过手动控制字符选取范围以及数量达到目的。例如只取前五位字母数字混合组成的新编号: ```java StringBuilder stringBuilder = new StringBuilder(5); for(int i=0;i<5;i++){ int number = val.nextInt(36); char ch = allChar.charAt(number); stringBuilder.append(ch); } String customUUIDPart = stringBuilder.toString(); Log.d("Custom Part",customUUIDPart); ``` 上述例子中,程序将会生成一段由五个随机挑选出来的英文字母加阿拉伯数字构成的小段落,适用于某些特殊场景下的简易标记用途[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值