For Java users that are interested in Sofien's solution, I have:
- Converted Sofien's code to Java and further simplified;
- Extensively tested on Android 10 (API 29), Android 11 (API 30) and previous versions.
1. Code and discussion
@Nullable
String getUniqueID() {
UUID wideVineUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
try {
MediaDrm wvDrm = new MediaDrm(wideVineUuid);
byte[] wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
return Arrays.toString(wideVineId);
} catch (Exception e) {
// Inspect exception
return null;
}
// Close resources with close() or release() depending on platform API
// Use ARM on Android P platform or higher, where MediaDrm has the close() method
}
There are two key differences w.r.t. Sofien's code.
- I am not using the
MessageDigest
, which results in a simpler code. Moreover, the MessageDigest.update()
method applies the SHA-256
hash function to its argument, which introduces an extremely low probability of losing UUID uniqueness. The only drawback of not hashing the UUID is that you don't have a fixed length UUID, which I don't care about in my application.
- Instead of the Kotlin function
toHexString
(which has no one-line counterpart in Java) I am using Arrays.toString
. This choice is safe because (A) It throws no Exception
and (B) it retains a one-to-one correspondence between the wideVineId
and its String
representation. If you prefer to stick to hex conversion, the Apache Commons Codec library offers a one-line solution.
Of course, these changes result in a different UUID, needless to say that other choices are possible. Notice also that an UUID generated with Arrays.toString
takes the form
[92, -72, 76, -100, 26, -86, 121, -57, 81, -83, -81, -26, -26, 3, -49, 97, -24, -86, 17, -106, 25, 102, 55, 37, 47, -5, 33, -78, 34, 121, -58, 109]
So, if you don't want special characters in your UUID you can remove them with String.replaceAll()
.
2. Tests
I have tested the persistence of the UUID
- over reinstallation
- over reinstallation AND reboot
on the following device/OS combinations:
- Google Pixel 4A / API 30
- Samsung Galaxy S10 / API 29
- Samsung Galaxy S9 / API 29
- Huawei Nexus 6P / API 27 (tested also factory reset)
- LG V20 / API 27 (tested also factory reset)
- Asus ZenFone 2 / API 23
- Samsung Galaxy J5 / API 23
- LG Nexus 5 / API 23
- LG K4 / API 22
- Samsung Galaxy J3 / API 22
- Samsung Galaxy S4 / API 21
In all of the tests, the targetSdkVersion
is 30. More tests (especially on API 29 and 30) are welcome.