This is a very important and interesting question, so would like to answer it in detail.
There are several ways of detecting an Android device uniquely, but the problem is that most of them are unreliable due to various reasons.
i) IMEI
This is by far the most common method used, but is only available for phones and needs this unnecessary permission android.permission.READ_PHONE_STATE
ii) Android ID
This can also get altered upon factory reset or if the device is rooted. Not a very reliable way for uniqueness.
iii) WLAN and Bluetooth MAC address
This requires devices to have these features and have take permissions like android.permission.ACCESS_WIFI_STATE
and android.permission.BLUETOOTH
. This will also not work if the wifi or bluetooth is turned off.
iv) Phone number or Email ID
This is the least reliable way to determine uniqueness and should not be a method of choice, if not entirely necessary.
So whats the way out now, Pseudo Unique ID. You can create your own "almost unique ID" from the device without any extra permissions.
Sounds good? Let's move on to the method directly.
/**
* Return pseudo unique ID
* @return ID
*/
public static String getUniquePsuedoID() {
// If all else fails, if the user does have lower than API 9 (lower
// than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
// returns 'null', then simply the ID returned will be solely based
// off their Android device information. This is where the collisions
// can happen.
// Thanks http://www.pocketmagic.net/?p=1662!
// Try not to use DISPLAY, HOST or ID - these items could change.
// If there are collisions, there will be overlapping data
String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// Thanks to @Roman SL!
// http://stackoverflow.com/a/4789483/950427
// Only devices with API >= 9 have android.os.Build.SERIAL
// http://developer.android.com/reference/android/os/Build.html#SERIAL
// If a user upgrades software or roots their device, there will be a duplicate entry
String serial = null;
try {
serial = android.os.Build.class.getField("SERIAL").get(null).toString();
// Go ahead and return the serial for api => 9
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
// String needs to be initialized
serial = "serial"; // some value
}
// Thanks @Joe!
// http://stackoverflow.com/a/2853253/950427
// Finally, combine the values we have found by using the UUID class to create a unique identifier
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
It takes various factors into consideration while generating a pseudo unique ID for any Android device. But this is not perfect.
There can be collisions of these IDs, but it will be rare, very very rare. So technically, this is something you can rely on for most use cases.