How to find serial number of Android device?

后端 未结 17 1961
借酒劲吻你
借酒劲吻你 2020-11-22 14:07

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 devi

相关标签:
17条回答
  • 2020-11-22 14:15

    Yes. It is a device hardware serial number and it is unique. So on api level 2.3 and above you can use android.os.Build.ANDROID_ID to get it. For below 2.3 API level use TelephonyManager.getDeviceID().

    you can read this http://android-developers.blogspot.in/2011/03/identifying-app-installations.html

    0 讨论(0)
  • 2020-11-22 14:16

    Build.SERIAL is the simplest way to go, although not entirely reliable as it can be empty or sometimes return a different value (proof 1, proof 2) than what you can see in your device's settings.

    There are several ways to get that number depending on the device's manufacturer and Android version, so I decided to compile every possible solution I could found in a single gist. Here's a simplified version of it :

    public static String getSerialNumber() {
        String serialNumber;
    
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class);
    
            serialNumber = (String) get.invoke(c, "gsm.sn1");
            if (serialNumber.equals(""))
                serialNumber = (String) get.invoke(c, "ril.serialnumber");
            if (serialNumber.equals(""))
                serialNumber = (String) get.invoke(c, "ro.serialno");
            if (serialNumber.equals(""))
                serialNumber = (String) get.invoke(c, "sys.serialnumber");
            if (serialNumber.equals(""))
                serialNumber = Build.SERIAL;
    
            // If none of the methods above worked
            if (serialNumber.equals(""))
                serialNumber = null;
        } catch (Exception e) {
            e.printStackTrace();
            serialNumber = null;
        }
    
        return serialNumber;
    }
    
    0 讨论(0)
  • 2020-11-22 14:17

    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 is 9774d56d682e549c. 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;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 14:17

    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 here http://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.

    0 讨论(0)
  • 2020-11-22 14:19

    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;
        }
    
    0 讨论(0)
  • 2020-11-22 14:21
    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.

    0 讨论(0)
提交回复
热议问题