PocketMagic

PocketMagic

Where Technology meets magic


Android
51 Posts
BlackBerry
6 Posts
Electronics
82 Posts
Hardware
139 Posts
High Voltage
56 Posts
Image processing
5 Posts
iPhone
4 Posts
Linux
2 Posts
Nuclear
26 Posts
Optics
11 Posts
Photography
7 Posts
Photoshop
3 Posts
Research
20 Posts
Reviews
18 Posts
Robotics
8 Posts
Security
9 Posts
Software
88 Posts
Symbian
2 Posts
Tubes
23 Posts
Windows Mobile
11 Posts

Sponsored Links


   

Top Articles!


Bluetooth and iOS - Use Bluetooth in your iPhone apps | 57832 Views | Rate 90.22
Bluetooth and iOS - Use Bluetooth in your iPhone apps
Simple Switched power Supplies | 59012 Views | Rate 82.3
Simple Switched power Supplies
AVR SDCard FAT support with FatFS | 16672 Views | Rate 64.12
AVR SDCard FAT support with FatFS
Programmatically Injecting Events on Android - Part 1 | 40746 Views | Rate 56.59
Programmatically Injecting Events on Android - Part 1

   

News & Updates


2014-04-15, Electric Fence Circuit for perimeter protection

2014-03-28, Infused™ project

2014-03-28, Discussing security in online on TV News show

2014-03-20, Global radiation monitoring network

 

  

Android Unique Device ID


By Radu Motisan Posted on February 1st, 2011 , 31524 Views (Rate 26.87)



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:

  1.  
  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
  10.  

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:

  1.  
  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();
  23.  

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

Here is the project code:
AndroidIDSample



More on PocketMagic:

Atmega8 and enc28J60 for ethernet support | 27537 Views | Rate 43.92
Atmega8 and enc28J60 for ethernet support
Using FS1000A/XY-FST RF Radio module with AVRs | 10718 Views | Rate 40.91
Using FS1000A/XY-FST RF Radio module with AVRs
A 3D Carousel View for Android | 12287 Views | Rate 39.64
A 3D Carousel View for Android
Android Bluetooth controlled robot - Part 1 | 45608 Views | Rate 36.05
Android Bluetooth controlled robot - Part 1
How to set the AVR Fusebits | 14224 Views | Rate 35.21
How to set the AVR Fusebits
Global radiation monitoring network | 9729 Views | Rate 34.5
Global radiation monitoring network

52 Responses to “Android Unique Device ID”

  1. 1
    carolsh:

    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
    Ridcully:

    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
    teh.fonsi:

    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
    teh.fonsi:

    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:

    Thanks.

  8. 8
    Jeff:

    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
    m&m:

    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
    Sapna:

    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
    Sapna:

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

  15. 15
    Sapna:

    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
    Sapna:

    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:
    http://www.pocketmagic.net/?p=1643

  18. 18
    Arun:

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

  19. 19
    andr_info:

    Thanks alot, really helped..

  20. 20
    Shoaib:

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

  21. 21
    Kevin:

    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
    Rk:

    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
    LSTT:

    Thank you. this article has been really really useful.

  26. 26
    LSTT:

    Thank you :D

  27. 27
    David:

    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
    Bright:

    Thanks a lot. ^^

  29. 29
    Rick:

    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
    HD:

    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
    IS:

    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
    gur:

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

    Thanks

  36. 36
    Pheonix:

    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?
    Thanks
    Nenad

  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
    Carl:

    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
    Ilya:

    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
    Martin:

    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
    Raj:

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

  50. 50
    Raj:

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

  51. 51
    Swapnil:

    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 .

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

Please copy the string j2Jn2D to the field below: