There are several occasions when the unique identifier of a device is required. For instance you need it to generate a serial key and unlock a trial version, to generate encryption keys or to have the unique signature of a device.
On Android there are several ways to get such an ID.

1. The IMEI: only for Android devices with Phone use:

  1. TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
  2. String szImei = TelephonyMgr.getDeviceId(); // Requires READ_PHONE_STATE

This requires adding a permission in AndroidManifest.xml, and users will be notified upon installing your software: android.permission.READ_PHONE_STATE. The IMEI is unique for your phone and it looks like this: 359881030314356 (unless you have a pre-production device with an invalid IMEI like 0000000000000).

2. Pseudo-Unique ID, that works on all Android devices
Some devices don't have a phone (eg. Tablets) or for some reason you don't want to include the READ_PHONE_STATE permission. You can still read details like ROM Version, Manufacturer name, CPU type, and other hardware details, that will be well suited if you want to use the ID for a serial key check, or other general purposes. The ID computed in this way won't be unique: it is possible to find two devices with the same ID (based on the same hardware and rom image) but the chances in real world applications are negligible. For this purpose you can use the Build class:

  2. String m_szDevIDShort = "35" + //we make this look like a valid IMEI
  3. Build.BOARD.length()%10+ Build.BRAND.length()%10 +
  4. Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
  5. Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
  6. Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
  7. Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
  8. Build.TAGS.length()%10 + Build.TYPE.length()%10 +
  9. Build.USER.length()%10 ; //13 digits

Most of the Build members are strings, what we're doing here is to take their length and transform it via modulo in a digit. We have 13 such digits and we are adding two more in front (35) to have the same size ID like the IMEI (15 digits). There are other possibilities here are well, just have a look at these strings.
Returns something like: 355715565309247 . No special permission are required, making this approach very convenient.

3. The Android ID , considered unreliable because it can sometimes be null. The documentation states that it "can change upon factory reset". This string can also be altered on a rooted phone.

  1. String m_szAndroidID = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

Returns: 9774d56d682e549c . No special permissions required.

4. The WLAN MAC Address string, is another unique identifier that you can use as a device id. Before you read it, you will need to make sure that your project has the android.permission.ACCESS_WIFI_STATE permission or the WLAN MAC Address will come up as null.

  1. WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
  2. String m_szWLANMAC = wm.getConnectionInfo().getMacAddress();

Returns: 00:11:22:33:44:55 (not a real address since this is a custom ROM , as you can see the MAC address can easily be faked). WLAN doesn't have to be on, to read this value.

5. The BT MAC Address string, available on Android devices with Bluetooth, can be read if your project has the android.permission.BLUETOOTH permission.

  1. BluetoothAdapter m_BluetoothAdapter = null; // Local Bluetooth adapter
  2. m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  3. String m_szBTMAC = m_BluetoothAdapter.getAddress();

Returns: 43:25:78:50:93:38 . BT doesn't have to be on, to read it.

Combined Device ID
Above, you have here 5 ways of reading a device unique identifier. Some of them might fail and return null, or you won't be able to use them because of the special permissions or because the hardware is missing (phone, bluetooth, wlan).
Nevertheless on all platforms you will find at least one that works. So a very good idea is to mix these strings, and generate a unique result out of their sum. To mix the strings you can simply concatenate them, and the result can be used to compute a md5 hash:

  2. String m_szLongID = m_szImei + m_szDevIDShort + m_szAndroidID+ m_szWLANMAC + m_szBTMAC;
  3. // compute md5
  4. MessageDigest m = null;
  5. try {
  6. m = MessageDigest.getInstance("MD5");
  7. e.printStackTrace();
  8. }
  9. m.update(m_szLongID.getBytes(),0,m_szLongID.length());
  10. // get md5 bytes
  11. byte p_md5Data[] = m.digest();
  12. // create a hex string
  13. String m_szUniqueID = new String();
  14. for (int i=0;i<p_md5Data.length;i++) {
  15. int b = (0xFF & p_md5Data[i]);
  16. // if it is a single digit, make sure it have 0 in front (proper padding)
  17. if (b <= 0xF) m_szUniqueID+="0";
  18. // add number to string
  19. m_szUniqueID+=Integer.toHexString(b);
  20. }
  21. // hex string to uppercase
  22. m_szUniqueID = m_szUniqueID.toUpperCase();

The result has 32 hex digits and it looks like this:
You can use it to generate any size unique string using hex digits or other sets of characters.

Here is the project code:

Related Post