http://stackoverflow.com/questions/2322234/how-to-find-serial-number-of-android-device



I need to use a unique ID for an Android app and I thought the serial number for the device would be a good candidate. How do I retrieve the serial number of an Android device in my app ?

share|improve this question
1 
Don't forget to add android:name="android.permission.READ_PHONE_STATE" to your manifest – Michael SIlveus Sep 30 '10 at 16:57 
1 
add comment
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

getSystemService is a method from the Activity class. getDeviceID() will return the MDN or MEID of the device depending on which radio the phone uses (GSM or CDMA).

Each device MUST return a unique value here (assuming it's a phone). This should work for any Android device with a sim slot or CDMA radio. You're on your own with that Android powered microwave ;-)

share|improve this answer
19 
@Hasemam its running fine now after adding <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> permission in androidManifest.xml file. –  Paresh Mayani Aug 26 '10 at 11:54
16 
There's some advice on the official Android developer's blog about using this identifier: android-developers.blogspot.com/2011/03/… –  David Caunt Apr 5 '11 at 11:12
7 
aside from the Android powered microwave, what about an Android powered Tablet? :) –  ajacian81 Aug 31 '11 at 13:38
12 
This method should be avoided, this will work on phones but will not work on devices without a phone chip (tablets being one example). From 2.3 you could use android.os.Build.SERIAL but check out the developer blog that @DavidCaunt suggested. –  John Mitchell Jan 2 '12 at 15:59
4 
Doesnt works on Tablet –  nicky Aug 18 '12 at 8:32
show 1 more comment

As Dave Webb mentions, the Android Developer Blog has an article that covers this.

I spoke with someone at Google to get some additional clarification on a few items. Here's what I discovered that's NOT mentioned in the aforementioned blog post:

  • ANDROID_ID is the preferred solution. ANDROID_ID is perfectly reliable on versions of Android <=2.1 or >=2.3. Only 2.2 has the problems mentioned in the post.
  • Several devices by several manufacturers are affected by the ANDROID_ID bug in 2.2.
  • As far as I've been able to determine, all affected devices have the same ANDROID_ID, which is9774d56d682e549c. Which is also the same device id reported by the emulator, btw.
  • Google believes that OEMs have patched the issue for many or most of their devices, but I was able to verify that as of the beginning of April 2011, at least, it's still quite easy to find devices that have the broken ANDROID_ID.

Based on Google's recommendations, I implemented a class that will generate a unique UUID for each device, using ANDROID_ID as the seed where appropriate, falling back on TelephonyManager.getDeviceId() as necessary, and if that fails, resorting to a randomly generated unique UUID that is persisted across app restarts (but not app re-installations).

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class DeviceUuidFactory {

    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";
    protected static volatile UUID uuid;

    public DeviceUuidFactory(Context context) {
        if (uuid == null) {
            synchronized (DeviceUuidFactory.class) {
                if (uuid == null) {
                    final SharedPreferences prefs = context
                            .getSharedPreferences(PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null);
                    if (id != null) {
                        // Use the ids previously computed and stored in the
                        // prefs file
                        uuid = UUID.fromString(id);
                    } else {
                        final String androidId = Secure.getString(
                            context.getContentResolver(), Secure.ANDROID_ID);
                        // Use the Android ID unless it's broken, in which case
                        // fallback on deviceId,
                        // unless it's not available, then fallback on a random
                        // number which we store to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId
                                        .getBytes("utf8"));
                            } else {
                                final String deviceId = ((TelephonyManager) 
                                        context.getSystemService(
                                            Context.TELEPHONY_SERVICE)
                                            .getDeviceId();
                                uuid = deviceId != null ? UUID
                                        .nameUUIDFromBytes(deviceId
                                                .getBytes("utf8")) : UUID
                                        .randomUUID();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }
                        // Write the value out to the prefs file
                        prefs.edit()
                                .putString(PREFS_DEVICE_ID, uuid.toString())
                                .commit();
                    }
                }
            }
        }
    }

    /**
     * Returns a unique UUID for the current android device. As with all UUIDs,
     * this unique ID is "very highly likely" to be unique across all Android
     * devices. Much more so than ANDROID_ID is.
     * 
     * The UUID is generated by using ANDROID_ID as the base key if appropriate,
     * falling back on TelephonyManager.getDeviceID() if ANDROID_ID is known to
     * be incorrect, and finally falling back on a random UUID that's persisted
     * to SharedPreferences if getDeviceID() does not return a usable value.
     * 
     * In some rare circumstances, this ID may change. In particular, if the
     * device is factory reset a new device ID may be generated. In addition, if
     * a user upgrades their phone from certain buggy implementations of Android
     * 2.2 to a newer, non-buggy version of Android, the device ID may change.
     * Or, if a user uninstalls your app on a device that has neither a proper
     * Android ID nor a Device ID, this ID may change on reinstallation.
     * 
     * Note that if the code falls back on using TelephonyManager.getDeviceId(),
     * the resulting ID will NOT change after a factory reset. Something to be
     * aware of.
     * 
     * Works around a bug in Android 2.2 for many devices when using ANDROID_ID
     * directly.
     * 
     * @see http://code.google.com/p/android/issues/detail?id=10603
     * 
     * @return a UUID that may be used to uniquely identify your device for most
     *         purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
}
share|improve this answer
1 
What permissions are required for an app to use this? –  Dave L. May 4 '11 at 13:28
1 
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission> – Gabrielle Nov 3 '11 at 12:34
1 
@ef2011 it's the double-checked locking pattern: en.wikipedia.org/wiki/Double-checked_locking –  emmbyJan 25 '12 at 19:55
1 
Thanks for posting. But what's to stop someone with a rooted phone from simply editing device_id.xml to put in a new UUID of their choice? (i.e. to circumvent a 'free trial' check) Wouldn't it be better if the class only stored the value in a preference file if it has to resort to the random ID method? Otherwise, there is no need to persist it between application runs; it's more secure to re-generate. –  Carlos P Jan 28 '12 at 13:06 
1 
"ANDROID_ID" is the preferred solution". Note that ANDROID_ID no longer uniquely identifies a device:stackoverflow.com/a/13465373/150016 –  Tom Dec 15 '12 at 19:35
show 5 more comments
String serial = null; 

try {
    Class<?> c = Class.forName("android.os.SystemProperties");
    Method get = c.getMethod("get", String.class);
    serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception ignored) {
}

This code returns device serial number using a hidden Android API.

share|improve this answer
3 
 
Thanks a ton this really helped me the other methods didn't survive wiping the device something i desperately needed this one doesn't change no matter what which i could do more than up vote –  user577732 Jan 27 '12 at 19:19
5 
this just gives me the same value as the one i get with android.os.Build.SERIAL –  Josephus Villarey Mar 9 '12 at 6:58
2 
android.os.Build.SERIAL is available from API level 9 –  Zelimir Jan 31 '13 at 11:44
 
Am I mistaken, or is this serial number the same in all devices with a specific custom rom? My device serial number (in eclipse device launcher) shows 01234567890ABC for a phone with a custom rom. –  Peterdk Jun 8 '13 at 20:35 
show 1 more comment
String deviceId = Settings.System.getString(getContentResolver(),
                                Settings.System.ANDROID_ID);

Although, it is not guaranteed that the Android ID will be an unique identifier.

share|improve this answer
 
its returns me null –  Paresh Mayani Aug 26 '10 at 11:56
 
@Paresh Mayani, It's hard to tell what may be the issue without looking at the code. My only assumption is that getContentResolver is returning null. However, it may be worth while opening a question and posting your code. –  Anthony Forloney Aug 26 '10 at 12:40
 
The emulator returns a null value, but I get a reasonable result when I run this code on my nexus one – emmby Sep 1 '10 at 21:36
3 
This ID comes from the Google account associated with the phone. The simulator typically does not have one. A real phone might not have one, either. Also, it's documented as "can change upon factory reset", and it can be changed arbitrarily anytime on a rooted phone. Use at your own risk. There's no good alternative - other tentative device IDs are either not universally available, or not unique, or both. See other answers for the rest of this sad story. –  Seva Alekseyev Feb 22 '11 at 16:13
add comment

There is an excellent post on the Android Developer's Blog discussing this.

It recommends against using TelephonyManager.getDeviceId() as it doesn't work on Android devices which aren't phones such as tablets, it requires the READ_PHONE_STATE permission and it doesn't work reliably on all phones.

Instead you could use one of the following:

  • Mac Address
  • Serial Number
  • ANDROID_ID

The post discusses the pros and cons of each and it's worth reading so you can work out which would be the best for your use.

share|improve this answer
 
+1, hi dave, thanx for the clarification because right now i am developing an application for the tablet, where i need to have Unique ID of the Android device, so what should i use to get Unique Android tablet device? – Paresh Mayani Apr 6 '11 at 6:34 
add comment

The IMEI is good but only works on Android devices with phone. You should consider support for Tablets or other Android devices as well, that do not have a phone.

You have some alternatives like: Build class members, BT MAC, WLAN MAC, or even better - a combination of all these.

I have explained these details in an article on my blog, see: http://www.pocketmagic.net/?p=1662

share|improve this answer
 
great article. 10x! +1 –  Ita Feb 8 '11 at 9:05
add comment

There are problems with all the above approaches. At Google i/o Reto Meier released a robust answer to how to approach this which should meet most developers needs to track users across installations.

This approach will give you an anonymous, secure user ID which will be persistent for the user across different devices (including tablets, based on primary Google account) and across installs on the same device. The basic approach is to generate a random user ID and to store this in the apps shared preferences. You then use Google's backup agent to store the shared preferences linked to the Google account in the cloud.

Lets go through the full approach. First we need to create a backup for our SharedPreferences using the Android Backup Service. Start by registering your app via this link:http://developer.android.com/google/backup/signup.html

Google will give you a backup service key which you need to add to the manifest. You also need to tell the application to use the BackupAgent as follows:

<application android:label="MyApplication"
         android:backupAgent="MyBackupAgent">
    ...
    <meta-data android:name="com.google.android.backup.api_key"
        android:value="your_backup_service_key" />
</application>

Then you need to create the backup agent and tell it to use the helper agent for sharedpreferences:

public class MyBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,          PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

To complete the backup you need to create an instance of BackupManager in your main Activity:

BackupManager backupManager = new BackupManager(context);

Finally create a user ID, if it doesn't already exist, and store it in the SharedPreferences:

  public static String getUserID(Context context) {
            private static String uniqueID = null;
        private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
    if (uniqueID == null) {
        SharedPreferences sharedPrefs = context.getSharedPreferences(
                MyBackupAgent.PREFS, Context.MODE_PRIVATE);
        uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
        if (uniqueID == null) {
            uniqueID = UUID.randomUUID().toString();
            Editor editor = sharedPrefs.edit();
            editor.putString(PREF_UNIQUE_ID, uniqueID);
            editor.commit();

            //backup the changes
            BackupManager mBackupManager = new BackupManager(context);
            mBackupManager.dataChanged();
        }
    }

    return uniqueID;
}

This User_ID will now be persistent across installations, even if the user switches devices.

For more information on this approach see Reto's talk herehttp://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html

And for full details of how to implement the backup agent see the developer site here:http://developer.android.com/guide/topics/data/backup.html I particularly recommend the section at the bottom on testing as the backup does not happen instantaneously and so to test you have to force the backup.

share|improve this answer
add comment

As @haserman says:

TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

But it's necessary including the permission in the manifest file:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
share|improve this answer
add comment

Another way is to use /sys/class/android_usb/android0/iSerial in an App with no permissions whatsoever.

user@creep:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
user@creep:~$ adb shell cat /sys/class/android_usb/android0/iSerial
0A3CXXXXXXXXXX5

To do this in java one would just use a FileInputStream to open the iSerial file and read out the characters. Just be sure you wrap it in an exception handler because not all devices have this file.

At least the following devices are known to have this file world-readable:

  • Galaxy Nexus
  • Nexus S
  • Motorola Xoom 3g
  • Toshiba AT300
  • HTC One V
  • Mini MK802
  • Samsung Galaxy S II

You can also see my blog post here: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html where I discuss what other files are available for info.

share|improve this answer
 
Thanks for posting your answer! Please be sure to read the FAQ on Self-Promotion carefully. Also note that it is required that you post a disclaimer every time you link to your own site/product. –  Andrew Barber Jan 31 '13 at 15:31
add comment

For a simple number that is unique to the device and constant for its lifetime (barring a factoring reset or hacking), use Settings.Secure.ANDROID_ID.

String id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

To use the device serial number (the one shown in "System Settings / About / Status") if available and fall back to Android ID:

String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);
share|improve this answer
add comment

I found the example class posted by @emmby above to be a great starting point. But it has a couple of flaws, as mentioned by other posters. The major one is that it persists the UUID to an XML file unnecessarily and thereafter always retrieves it from this file. This lays the class open to an easy hack: anyone with a rooted phone can edit the XML file to give themselves a new UUID.

I've updated the code so that it only persists to XML if absolutely necessary (i.e. when using a randomly generated UUID) and re-factored the logic as per @Brill Pappin's answer:

import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

public class DeviceUuidFactory {
    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";

    protected static UUID uuid;

    public DeviceUuidFactory(Context context) {

        if( uuid ==null ) {
            synchronized (DeviceUuidFactory.class) {
                if( uuid == null) {
                    final SharedPreferences prefs = context.getSharedPreferences( PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null );

                    if (id != null) {
                        // Use the ids previously computed and stored in the prefs file
                        uuid = UUID.fromString(id);

                    } else {

                        final String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);

                        // Use the Android ID unless it's broken, in which case fallback on deviceId,
                        // unless it's not available, then fallback on a random number which we store
                        // to a prefs file
                        try {
                             if ( "9774d56d682e549c".equals(androidId) || (androidId == null) ) {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

                                if (deviceId != null)
                                {
                                    uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
                                }
                                else
                                {
                                    uuid = UUID.randomUUID();

                                    // Write the value out to the prefs file so it persists
                                    prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
                                }
                            }
                            else
                            {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                            } 
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }



                    }

                }
            }
        }

    }


    /**
     * Returns a unique UUID for the current android device.  As with all UUIDs, this unique ID is "very highly likely"
     * to be unique across all Android devices.  Much more so than ANDROID_ID is.
     *
     * The UUID is generated by using ANDROID_ID as the base key if appropriate, falling back on
     * TelephonyManager.getDeviceID() if ANDROID_ID is known to be incorrect, and finally falling back
     * on a random UUID that's persisted to SharedPreferences if getDeviceID() does not return a
     * usable value.
     *
     * In some rare circumstances, this ID may change.  In particular, if the device is factory reset a new device ID
     * may be generated.  In addition, if a user upgrades their phone from certain buggy implementations of Android 2.2
     * to a newer, non-buggy version of Android, the device ID may change.  Or, if a user uninstalls your app on
     * a device that has neither a proper Android ID nor a Device ID, this ID may change on reinstallation.
     *
     * Note that if the code falls back on using TelephonyManager.getDeviceId(), the resulting ID will NOT
     * change after a factory reset.  Something to be aware of.
     *
     * Works around a bug in Android 2.2 for many devices when using ANDROID_ID directly.
     *
     * @see http://code.google.com/p/android/issues/detail?id=10603
     *
     * @return a UUID that may be used to uniquely identify your device for most purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
share|improve this answer
 
Putting the id into shared prefs compromises original aim to get really unique id. E.g. you if you want to use that id as key for some restrictions then you will be screwed when skilled users root a device and got access to your shared preference file. Its contents may be copied which means... –  Eugene Wechsler Aug 8 '11 at 17:18
 
there is also one other error to MB's answer and yours..If you use randomUUID as a deviceID and appID it works for all devices across the boord no matter if they are phones or not or if they are google exp devices or not. –  Fred Grott Jan 31 '12 at 18:08 
add comment