Where Technology meets magic

53 Posts
6 Posts
84 Posts
142 Posts
High Voltage
57 Posts
Image processing
5 Posts
4 Posts
3 Posts
27 Posts
11 Posts
7 Posts
3 Posts
21 Posts
19 Posts
9 Posts
9 Posts
91 Posts
2 Posts
23 Posts
Windows Mobile
11 Posts

Sponsored Links


Top Articles!

AVR SDCard FAT support with FatFS | 19635 Views | Rate 38.8
AVR SDCard FAT support with FatFS
Single Chip Computer | 1873 Views | Rate 29.27
Single Chip Computer
3V to 400V regulated inverter for Geiger counters | 2921 Views | Rate 18.72
3V to 400V regulated inverter for Geiger counters
Virtualmin Git return code 22 fatal: git-http-push failed | 113 Views | Rate 14.13
Virtualmin Git return code 22 fatal: git-http-push failed


News & Updates

2014-12-12, Virtualmin Git return code 22 fatal: git-http-push failed

2014-11-25, Electric Fence - 20KV pulses for perimeter defense

2014-10-29, Statie de monitorizare a radiatiei de fond in Timisoara

2014-10-29, uRADMonitor - Online Radiation monitoring station



Android Unique Device ID

By Radu Motisan Posted on February 1st, 2011 , 8383 Views (Rate 5.91)

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:

More on PocketMagic:

Atmega8 and enc28J60 for ethernet support | 8764 Views | Rate 10.03
Atmega8 and enc28J60 for ethernet support
How to set the AVR Fusebits | 6436 Views | Rate 9.9
How to set the AVR Fusebits
Custom Rotary Knob Control for Android | 3969 Views | Rate 9.66
Custom Rotary Knob Control for Android
Programmatically Injecting Events on Android - Part 1 | 8973 Views | Rate 9.29
Programmatically Injecting Events on Android - Part 1
Variable 0..30V Regulated Power supply for 20A max | 15322 Views | Rate 8.69
Variable 0..30V Regulated Power supply for 20A max
Discussing security in online on TV News show | 2672 Views | Rate 8.48
Discussing security in online on TV News show

55 Responses to “Android Unique Device ID”

  1. 1

    Thank you Radu..it help me a lot and save my precious time :) cheers..more power and keep on enlightening us..:)

  2. 2
    Radu Motisan:

    Thank you for your feedback, I’m happy this helped.

  3. 3

    Thank you, exactly what I was looking for. Would have taken quite a while to figure out all possibilities.

  4. 4
    Radu Motisan:

    Glad this helps.

  5. 5

    Thank you, the pseude unique id was very helpful because i needed the unique id in a class and not in an activity.

  6. 6

    the pseude unique id was very helpful because i needed the unique id in a class and not in an activity. thanks for sharing

  7. 7
    Radu Motisan:


  8. 8

    Concerning approach #2, wouldn’t this method fail the moment a user updates its Android version?

  9. 9
    Radu Motisan:

    Hi Jeff,

    The OS version number would change, but how often do you expect this to happen? If you’re using this for a serial key, you can simply supply a new one to the user.

  10. 10

    Hi Radu,
    Helpful article, but I’d have one notice: WLAN MAC and BT MAC cannot be read (they’ll be null) if the WIFI is OFF or BT is OFF, on Samsung Galaxy S, for example. However, it works on Nexus.

  11. 11
    Radu Motisan:

    hi m&m, an excellent remark, thank you.

  12. 12

    why all the apps of pocket magic are failed to run is there any changes in need to do in apps

  13. 13
    Radu Motisan:

    @Sapna, what exactly doesn’t work?

  14. 14

    im working on eclipse
    is there any other tool for android ?

  15. 15

    well i import this app into eclipse and when i star running in emulator ON STARTING OF ACTIVITY NO PAGE DISPLAYED AND A MSG “APPLICATION STOPPED UNEXPECTEDLY”

  16. 16

    Plz reply Radu its an big issue when ever i download any app from net it happens so is it about the android target version i m using

  17. 17
    Radu Motisan:

    @Sapna, try reinstalling your tools, see these guides to do it correctly:

  18. 18

    @Sapna try setting the m_szUniqueID=(some 32 hex value) . Your program might have been crashing due to null value.

  19. 19

    Thanks alot, really helped..

  20. 20

    Hi.. Can BT MAC Address be faked any how??

  21. 21

    Could you put some kind of a license on this code so that others can use it? Ideally Apache 2 or another recognized license?

  22. 22
    Radu Motisan:

    Kevin, thanks for asking. You can use the code for free, both in non-commercial and commercial applications. It would be nice if you would indicate the source (My name or this page).

  23. 23

    how to find unique identifier in Android phones and tablets for same apps.

  24. 24
    Radu Motisan:

    Rk, I think I don’t understand your question. To find a unique ID, use the code in the article.

  25. 25

    Thank you. this article has been really really useful.

  26. 26

    Thank you :D

  27. 27

    I just need to make a comment about approach #4:
    the MAC address DOES change on my phone. When I turn off the WIFI. switch off my phone, then switch it back on. The MAC address reads as null.

  28. 28

    Thanks a lot. ^^

  29. 29

    Awesome Thanks If it is OK with you I would like to re-post this. Of-course with a link here and your name.

  30. 30
    Radu Motisan:

    @Rick: ok.

  31. 31

    Hi, great article, but can you PLEASE tell me how an ID returned by your algorithm can CHANGE over the lifetime of the device?? For example, we know that doing a factory reset of the device will create a new Secure.ANDROID_ID, and therefore change the output of the Hex digest. So again, how else can the algorithm’s Hex digest change over the lifetime of the device? I hope I’m making sense; thank you for your time.

  32. 32
    Radu Motisan:

    @HD. Thank you. Yes your question makes sense perfectly, and I should add the answer to the article: This ID will change over the lifetime of device, including when doing a factory reset.
    So take this into account when using it!

  33. 33

    Thank you for a great and very helpful article. But of that:

    Build.BOARD.length()%10+ Build.BRAND.length()%10 +
    Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
    Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
    Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
    Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
    Build.TAGS.length()%10 + Build.TYPE.length()%10 +
    Build.USER.length()%10 ; //13 digits

    What can be changed after a factory reset?

  34. 34
    Radu Motisan:

    @IS, indeed this is the right way to go: using only those identifiers that remain unchanged. I haven’t tested all of them, but you can reduce them to a number you are certain will remain unchanged.

  35. 35

    Can the ID (device/user/MAC etc.) be collected if my APP is HTML ?


  36. 36

    Thanks a lot. Am using the last technique of yours, which is a combination of all. Hope it doesn’t require any special permission.

  37. 37
    čikić Nenad:

    I am looking also for unique id.
    What I see is that you have excluded the SERIAL (from api 9).
    It should give serial hardware number so it shouldn’t change with firmware upgrade.
    Any particular reason for excluding SERIAL?

  38. 38
    Radu Motisan:

    I need this to work with older apis too.

  39. 39
    lukas mueller:

    with the update to jelly bean 4.2. the unique-id of the device changes from the one of 4.1.. anyone knows why?

  40. 40
    Radu Motisan:

    this is the expected behavior.

  41. 41
    lukas mueller:

    ok, thx.
    is it because of Build.ID ?

  42. 42

    Quite a few Build attributes could change as the result of an over-the-air update. Some, however, are less likely to change than others. I’d suggest identifying the ones that would change and using only the ones that would not.

    ANDROID_ID, if available, can be used without any of the other stuff, and will only change on a factory reset. The value given above as its returned value, 9774d56d682e549c, is returned only for a particular, limited set of devices that have implemented this value incorrectly. In other words, the presence of this value indicates a bug with ANDROID_ID on the device which should cause that value to not be used (unless you want to use it in combination with other values because it at least limits the ID to the set of devices having that buggy code). Otherwise, you can use it without the Build or other values, because why contaminate a good ANDROID_ID value with Build values that may change as the result of an OTA update?

    Regarding Build.SERIAL, why not use reflection to detect whether it is available, and use it if it is? This value is required to be present on devices that have no telephony, for Android releases starting at Gingerbread (API Level 9). It should be unique when it is available.

  43. 43
    Radu Motisan:

    @Carl, some very good suggestions.

  44. 44
    Mohammed Munzaleen:

    I would like to know whether the IMEI number and Android ID are the same?

  45. 45
    Radu Motisan:

    @Mohammed : no, they are not.

  46. 46

    Why not use Build.SERIAL, in try-catch, with fallback to ANDROID_ID, with fallback (in case of null, or buggy value) to anything pseudo unique like SecureRandom uuid?
    Another question, does anyone know which of all that was talked here is usable in BlackBerry android player?

  47. 47

    Thank you Radu, this is just great! Do you have anything like this for an iPhone och iPad as well?

  48. 48
    Radu Motisan:

    @Martin, yes you can use the same approach for ios.

  49. 49

    Thanks. This has really helped me a lot. It saved my huge R & D time. Thanks once again.

  50. 50

    This has really helped me a lot. It saved my huge R & D time. Thanks once again.

  51. 51

    String m_szBTMAC = m_BluetoothAdapter.getAddress();
    Returns “” when Bluetooth is OFF
    AND some value (like A0:F4:50:E6:5D:9C) when Bluetooth is ON

    So it affects final m_szUniqueID.

    How to overcome this?

  52. 52
    Radu Motisan:

    @Swapnil, simply exclude the m_szBTMAC from your m_szUniqueID .

  53. 53
    Aspirin Vagrant:

    Usually, a mobile device can be characterized as: android id, mac, imei etc. But these features could modified by system upgrade or falsification. How can I distinguish system upgrade or falsification? For example:

    system upgrade:
    android id1 mac1 imei1 ==> device1
    android id2 mac1 imei1 ==> device1

    android id1 mac1 imei1 ==> device1
    android id2 mac1 imei1 ==> device2(android id2 mac2 imei2)

    Can you give me some tips?

  54. 54
    How to: Is there a unique Android device ID? | SevenNet:

    […] } assertPermission(ctx, permission.BLUETOOTH); return ba.getAddress(); } } // TODO PSEUDO_ID // http://www.pocketmagic.net/2011/02/android-unique-device-id/ ; static final String BUGGY_ANDROID_ID = "9774d56d682e549c"; private final static String TAG = […]

  55. 55
    How to: Is there a unique Android device ID? | Technical information for you:

    […] } assertPermission(ctx, permission.BLUETOOTH); return ba.getAddress(); } } // TODO PSEUDO_ID // http://www.pocketmagic.net/2011/02/android-unique-device-id/ ; static final String BUGGY_ANDROID_ID = "9774d56d682e549c"; private final static String TAG = […]

Thank you for commenting. Your comment won't show until approved, which can take some time.