How to generate Android Unique ID

William Gouvea
ProAndroidDev
Published in
5 min readMar 13, 2020

--

Generate unique ID at Android platform is a recurring theme among developers and it’s very important in order to perform:

  • app installs/uninstalls
  • user behavior in anonymous mode.
  • ads campaigns
  • point of attention
  • client/server communication
  • login validation
  • in-app purchase verification
  • licensing purposes

There is no unique answer to that question ( you’ve got the pun) , but throughout the years many people has think about it and create inventive solutions to this subject.

Actually this kind of problem still happens in others platforms, mainly in web since there is no reliable way to know for certain , who that anonymous user is and which devices he is using.

A simple Google search and you can find some StackOverflow threads which can enlighten your pursuit, but instead of just copy and paste the first checked answer, as a good developer , you should analyze all alternatives and this post can help you out.

Google recommendation is described below in 4 basic points:

Avoid using hardware identifiers. In most use cases, you can avoid using hardware identifiers, such as SSAID (Android ID), without limiting required functionality. Android 10 (API level 29) adds restrictions for non-resettable identifiers, which include both IMEI and serial number. Your app must be a device or profile owner app, have special carrier permissions, or have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access these identifiers.

Only use an Advertising ID for user profiling or ads use cases. When using an Advertising ID, always respect users’ selections regarding ad tracking. Also, ensure that the identifier cannot be connected to personally identifiable information (PII), and avoid bridging Advertising ID resets.

Use an Instance ID or a privately stored GUID whenever possible for all other use cases, except for payment fraud prevention and telephony. For the vast majority of non-ads use cases, an Instance ID or GUID should be sufficient.

Use APIs that are appropriate for your use case to minimize privacy risk. Use the DRM API for high-value content protection and the SafetyNet APIs for abuse protection. The SafetyNet APIs are the easiest way to determine whether a device is genuine without incurring privacy risk.

If for some reason, I don’t have time or don’t wanna follow Google’s advices , what are the alternatives?

Pseudo Unique ID

Pseudo Unique ID is basically a generated string, often encoded in base64 created by many data pieces together.

For instance if you are developing an video streaming app ,you should be tempted to use one strategy like movieId + usedId + timestamp(seconds precision) to validate session as DRM, which is strictly discouraged, since Android has one good media DRM API in the platform.

Likewise if you are working in an app store or marketplace kind of product, the most easy thinkable approach could be one pseudo ID which concat IMEI, Build.Serial , ANDROID_ID and MAC_ADDRESS , but since Android 6 , it’s not a good idea and this is why.

MAC ADDRESS

Most of the references and posts spot this as a valid device identifier, however since Android 6 Marshmallow , Google has “nerfed” this , make it returns an constant value 02:00:00:00:00:00.

Updated April 2020

MAC address randomization

On devices that run Android 10 or higher, the system transmits randomized MAC addresses by default.

More at docs

IMEI/IMSI/ESN/PhoneNumber

You can access phone info easily using snippet in gist above, but in order to fetch those info, you need put one more permission at AndroidManifest.xml

Since Android 6, these permission has been put under runtime permissions category, which means you don’t grant it by default at installation and need to add some code in order to ask it for user approval, and depending on what your app does, it can be viewed as suspicious.

Likewise, even if user grant it to you, it doesn’t work reliably. When it does work, that value survives device wipes (“Factory resets”) and thus you could end up making a nasty mistake when one of your customers wipes their device and passes it on to another person.

Also it this can return wrong or useful values as null ,”” ,”???????”, constants or a stale phone number that is no longer valid.

Updated April 2020

Restriction on non-resettable device identifiers

Starting in Android 10, apps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number.

Caution: Third-party apps installed from the Google Play Store cannot declare privileged permissions.

More at docs

Secure ID

Settings.Secure.ANDROID_ID is a 64 bit hex String generated when device is first setup, but it’s sensitive to factory resets. You can use code below:

However there is some changes at Android 8 Oreo where the ANDROID_ID value is unique to each combination of app-signing key, user, and device, being scoped by signing key and user.

Build.SERIAL

Build.SERIAL field have been used widely since API 9 Gingerbread and used to return hardware serial needed by telco’s.

However has been deprecated in Android 8 , and after Android 9 , you need some privileged permissions at image level or it returns Build#UNKNOWN , here is the explanation.

You also be able to use some data info from device provided by Build class , for instance , in order to have such a device profile, which in worst case can be used to segment different audience. This technique is still used by Firebase, Crashlytics and many other analytics tracker and crash report SDK tools.

Conclusion

In the end, if you don’t wanna follow Google’s advices , the most easy and reliable way to get job done is:

It can be saved in a durable way in the storage regarding your use case, which is out of the scope of the post.

References

--

--

Dad, Husband, Curious, Pet Lover and also Android Specialist - Reverse Engineer Specialist - Senior Backend Developer.