Android Universal User ID, for Android Freaks Everywhere
Many of us android application developers develop for many AppStore platforms such as Google Play Store, Amazon AppStore, and many others which requires as much as we may like Google Play Services a Google Play Services agnostic solution. On top of that with Android M release we no longer have a certain hardware IDs to use to generate a User ID and thus we need a better solution.
A Universal User ID, or if you will UUID, gets used for several things. It can be the unique ID to determine if its a unique application installation in the case of us wanting to collect application use statistics. It can help us track bug reports in case of ANRs. It just makes good developer best practices sense to have a Universal User ID for every user of your application.
MATH IS HARD
Yes, we will touch on math a little bit. Do not worry you will not be force to think very hard. Right now we have about 1.5 billion Android Device users and Google has about 1 billion GMail users.
To complicate matters we have two android device form factors that have possible multi-users, the android tablet and the android TV. When Unix was created in the 1970s they could only envision progress so far and only used 64bit numbers for machine ID.
The hardware IDs that android might use are based on this, for example the WIFI MAC is 64bit, so is the simCard ID, and so is the machine deviceID for cellular networks. At 100 to 300 million tablets that does not sound too bad but at 500 million multi-user devices combined with the potential app to have 1 billion installs we start to run into number clash problems as 64bit is only about:
2⁶⁴ = 18,000,0000 trillion
Thus, in no clash theory we could use Android_ID via Settings.Secure and we would still get an encrypted hashed copy of the machine ID for our own use as an application ID. What is the problem with that?
With Android 6.x we got the benefit of encrypted disks in that on those Android Devices the user can have the whole thing encrypted. Rooting wise, its impossible for a thief to root break an Android Device that has been User encrypted. But not every device owner is educated yet to fully enable that even with the Snowden revelations. You should do it by-the-way as an android device user and owner as it protects you in so many ways.
For those that still have Android 4.x devices, they are still susceptible to a thief grabbing the device and rooting to get the unencrypted Android_ID and other information to steal people’s identities.
Providing a slight obstacle to the bad guys and bad girls doing that is just a good best practice to have in place. Plus, its somewhat fun to think of those bad guys and bad girls having a bad time in breaking into something. Not as fun as watching them have a bad time, which is why I envy devops developers sometimes.
The Java Language itself has an UUID class to allow use to compute a 128bit UUID using the most significant bits and least significant bits and also a random method to generate an unique UUID. We will use the random method.
We have two things to do check if the UUID has been generated and stored and if not than compute an UUID and store it as encrypted. And we know that this particular class we come up with will be used in the extended Application class so we need to make sure that we handle SharedPreferences storage correctly as we are or still will be on the main thread.
Okay, let’s step through this class. You know what protected static final does as far as protecting the two variables, PREFS_FILE and PREFS_DEVICE_UUID, from third party manipulation. You cannot even grab it via reflection.
Any one of you know why we are using:
protected volatile static UUID uuid;
With the other two variables we did not have to worry about Atomic behavior or word tear, but the UUID is a 128bit number so in our locking down to one thread(synchronized (DroidUuidFactory.class)) we want the variable to be written once and seen right away as a number to be read by other threads.
We all live in this multi-CPU android device environment, even my low end $100 android phone has a multi-cpus. In such a multi-threaded environment synchronizing SharedPreferences editing is somewhat mandatory.
True, if the class WAS GUARANTEED TO ONLY BE CALLED AS A METHOD IN THE EXTENDED APPLICATION CLASS than I would not have to probably worry so much about threading. But, if I put the call in an activity instead for a small application the activity is not a guaranteed as a singleton in multi-cpu multi-threaded environments. So I implemented the class in such a way that it can be used both with extended Application classes and activity classes.
That is part of library design in determining all the use cases for the class and designing the class appropriately to handle all the use cases. That is a learned habit and skill. Do not worry you will get that skill, just keep practicing and you will find that that skill starts to take shape as you progress in programming.
Rest of the code is just cycling through our logic in checking if the UUID has been stored and or computed.
Did you notice that I did not encrypt randomUUID?
Let’s step through the reasons why. One, in not using anything that has a real ID in it I avoid information leakage and avoid having to prompt a user for granting permission for the read phone state(A GOOD IDEA!). Two, encryption has a speed performance penalty and this class gets used in the extended Application class initialization so it has to return from the method call in a fast way.
To use the class its just in the extended Application class onCreate method:
DroidUuidFactory myUUId =new DroiodUuidFactory(context);
So in showing best practices in computing a unique UUID I have given you a taste of best practices in threading on multiple cpus, security and information leakage on mobile devices, etc. Good development habits to have in Android Application Development.
As a side benefit we get some cross App-Store independence to use this class with android applications that are deployed to other than Google Play Store and by not using any information secret to the phone we also avoid having to prompt the user to unnecessarily grant the read phone state permission.
If you are a Chicago funded Start-Up(If not than you might have to accept me remote coding) and seeking a Senior Android Application Developer unicorn, you may like my thinking and methods and my contact directions and information are in the link below. But please, I prefer co-founders to contact me rather than recruiters or HR.