Getting a unique ID signature for every android device

A problem often encountered while trying to keep track on your users actions is how to get a device identification

A problem often encountered while trying to keep track on your users actions is how to get a device identification for every user that installed your application. There is no method that will give you a definite and unique ID, but there are a few of them that are stated as 99% sure. We will give you a simple Class that uses all those methods in order to give you confidence.

Before presenting the class itself, you should know that this class doesn’t handle the caching of the ID in database. You have to make those implementations yourself. We are using the Settings.get() and Settings.set() methods of our own settings class that handles the simple database based key-value settings implementation. I will write about that exact system in one of my next posts, so make sure you follow our blog or social profiles (links are to the right) on a regular basis :).

Finally, the class itself

// ---------------------------------------
// Class: DeviceID
// Usage: Generate a unique ID for your
//        app installation
// ---------------------------------------

public class DeviceID {
  private static String ID = null;
	static Context context;
	
	// return a cached unique ID for each device
	public static String getID() {
		
		// if the ID isn't cached inside the class itself
		if (ID == null) {
			//get it from database / settings table (implement your own method here)
			ID = Settings.get("DeviceID");
		}
		
		// if the saved value was incorrect
		if (ID.equals("0")) {
			// generate a new ID
			ID = generateID();
	
			if (ID != null) {
				// save it to database / setting (implement your own method here)
				Settings.set("DeviceID", ID);
			}
		}
		
		return ID;
	}

	// generate a unique ID for each device
	// use available schemes if possible / generate a random signature instead 
	private static String generateID() {
		
		// use the ANDROID_ID constant, generated at the first device boot
		String deviceId = Secure.getString(context.getContentResolver(),
                Secure.ANDROID_ID);

		// in case known problems are occured
		if ("9774d56d682e549c".equals(deviceId) || deviceId == null) {

			// get a unique deviceID like IMEI for GSM or ESN for CDMA phones
			// don't forget:
                        //    
			deviceId = ((TelephonyManager) context
                                                       .getSystemService( Context.TELEPHONY_SERVICE ))
                                                       .getDeviceId();

			// if nothing else works, generate a random number
			if (deviceId == null) {

				Random tmpRand = new Random();
				deviceId = String.valueOf(tmpRand.nextLong());
			}
			
        }
		 
		// any value is hashed to have consistent format
		return getHash(deviceId);
	}
	
	// generates a SHA-1 hash for any string
    public static String getHash(String stringToHash) {

    	MessageDigest digest = null;
		try {
			digest = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		
    	byte[] result = null;
    	
		try {
			result = digest.digest(stringToHash.getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

    	StringBuilder sb = new StringBuilder();

    	for (byte b : result)
    	{
    	    sb.append(String.format("%02X", b));
    	}

    	String messageDigest = sb.toString();
    	return messageDigest;
    }
}

Usage

The usage is as simple as it gets:

String myID;
myID = DeviceID.getID();

Other than the comments in code above, let me just walk you through the methods of getting the ID:

  • First, try to get the ID from database
  • Second, try to generate the ID based on Androids random ID generated on first boot
  • Third, try to generate the ID based on IMEI for GSM or ESN for CDMA
  • Last, simply generate your own random ID

Generating AndroidID in this order gives you a more than enough safe way to get a unique signature. Generation occurs only the first time, and later on uses cache to fetch the ID.

If you have any questions feel free to leave them on the form underneath, and also add Profico on social pages (links are in the right column) to keep track of other cool articles 🙂

8 thoughts on “Getting a unique ID signature for every android device

  1. Thanks man, but that do not identify a device as -> Android.ID can be changed, so if it does, the phone does not get the same unique id anymore.
    Plus, the generate a random number thing can’t be map to the device itself, so you’re not able to say “ok, this device is associated and will always be associated with this id”.

    1. Hi Tux,

      Yes, you are right, but there is actually no way to solve that problem if you involve somebody willing to inflate the system and change devices AndroidID, or try to go around any other method you use. Thus being said, our method does offer you a unique ID in high percent of cases (like i mentioned above).

      Best regards,

      Ante

    1. Hi Rene,

      are your additions targeted on base topic or you added something specific regarding your app/logic? If you have improved the main idea we could set up a github repo or maybe a gist, and we’ll be very glad to see your contribution inside pull request 🙂

  2. One question: On a Sprint or Verizon worldphone (either CDMA or GSM, depending on location), will your generateID() create the same ID for both London (GSM) and New York (CDMA) on the same device?

  3. Karl,

    The answer to your question depends on the success of the attempt to use ANDROID_ID at the start of the generateID method. This should work on the large majority of devices, but if for some reason this were to return null or be the known infamous “duplicate value” checked for in the code here, then it would fallback to the TelephonyManager method which has a high chance of being different on GSM vs CDMA.

    In summary, this method has a high probability of returning a unique device ID, but when that fails, defaults to returning either the TelephonyManager unique ID or an installation-scoped ID. That final fallback to an installation-scoped ID is a questionable choice; personally I would have chosen to return null and have a separate Installation ID method (such as the one shown here http://android-developers.blogspot.com/2011/03/identifying-app-installations.html) and let callers decide whether they want to use that or gracefully fail rather than deliver without warning an installation ID which may change if users uninstall the app or clear data from the application manager. The use case for a device ID may be very different from the use case for an installation ID and it is dangerous to return the latter without warning the caller of this difference.

    Regardless, this method should not be used in any situation that expects a 100% reliable result. Unfortunately there IS NO WAY to get a perfectly reliable unique device ID on Android. Please everyone just keep this in mind when designing your use cases for this code so we’re all a little bit safer!

  4. Hi,

    I have a made an image of my android tablet device using Clonezilla. I want to deploy this image to a number of tablets but the issue I now have is the Device ID will be the same for each device. Is there a way to change the Device ID or generate a new ID without rooting or factory data reset? Is it possible to delete the Device ID from the image (by opening it) and on first boot it will generate a new ID?

Leave a Reply