How to find serial number of Android device?

后端 未结 17 1963
借酒劲吻你
借酒劲吻你 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:24

    Starting in Android 10, apps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number.

    Affected methods include the following:

    Build getSerial() TelephonyManager getImei() getDeviceId() getMeid() getSimSerialNumber() getSubscriberId()

    READ_PRIVILEGED_PHONE_STATE is available for platform only

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

    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.

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

    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.

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

    Since no answer here mentions a perfect, fail-proof ID that is both PERSISTENT through system updates and exists in ALL devices (mainly due to the fact that there isn't an individual solution from Google), I decided to post a method that is the next best thing by combining two of the available identifiers, and a check to chose between them at run-time.

    Before code, 3 facts:

    1. TelephonyManager.getDeviceId() (a.k.a.IMEI) will not work well or at all for non-GSM, 3G, LTE, etc. devices, but will always return a unique ID when related hardware is present, even when no SIM is inserted or even when no SIM slot exists (some OEM's have done this).

    2. Since Gingerbread (Android 2.3) android.os.Build.SERIAL must exist on any device that doesn't provide IMEI, i.e., doesn't have the aforementioned hardware present, as per Android policy.

    3. Due to fact (2.), at least one of these two unique identifiers will ALWAYS be present, and SERIAL can be present at the same time that IMEI is.

    Note: Fact (1.) and (2.) are based on Google statements

    SOLUTION

    With the facts above, one can always have a unique identifier by checking if there is IMEI-bound hardware, and fall back to SERIAL when it isn't, as one cannot check if the existing SERIAL is valid. The following static class presents 2 methods for checking such presence and using either IMEI or SERIAL:

    import java.lang.reflect.Method;
    
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.provider.Settings;
    import android.telephony.TelephonyManager;
    import android.util.Log;
    
    public class IDManagement {
    
        public static String getCleartextID_SIMCHECK (Context mContext){
            String ret = "";
    
            TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
    
            if(isSIMAvailable(mContext,telMgr)){
                Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId());
                return telMgr.getDeviceId();
    
            }
            else{
                Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
    
    //          return Settings.Secure.ANDROID_ID;
                return android.os.Build.SERIAL;
            }
        }
    
    
        public static String getCleartextID_HARDCHECK (Context mContext){
            String ret = "";
    
            TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            if(telMgr != null && hasTelephony(mContext)){           
                Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId() + "");
    
                return telMgr.getDeviceId();    
            }
            else{
                Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);
    
    //          return Settings.Secure.ANDROID_ID;
                return android.os.Build.SERIAL;
            }
        }
    
    
        public static boolean isSIMAvailable(Context mContext, 
                TelephonyManager telMgr){
    
            int simState = telMgr.getSimState();
    
            switch (simState) {
            case TelephonyManager.SIM_STATE_ABSENT:
                return false;
            case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
                return false;
            case TelephonyManager.SIM_STATE_PIN_REQUIRED:
                return false;
            case TelephonyManager.SIM_STATE_PUK_REQUIRED:
                return false;
            case TelephonyManager.SIM_STATE_READY:
                return true;
            case TelephonyManager.SIM_STATE_UNKNOWN:
                return false;
            default:
                return false;
            }
        }
    
        static public boolean hasTelephony(Context mContext)
        {
            TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm == null)
                return false;
    
            //devices below are phones only
            if (Build.VERSION.SDK_INT < 5)
                return true;
    
            PackageManager pm = mContext.getPackageManager();
    
            if (pm == null)
                return false;
    
            boolean retval = false;
            try
            {
                Class<?> [] parameters = new Class[1];
                parameters[0] = String.class;
                Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
                Object [] parm = new Object[1];
                parm[0] = "android.hardware.telephony";
                Object retValue = method.invoke(pm, parm);
                if (retValue instanceof Boolean)
                    retval = ((Boolean) retValue).booleanValue();
                else
                    retval = false;
            }
            catch (Exception e)
            {
                retval = false;
            }
    
            return retval;
        }
    
    
    }
    

    I would advice on using getCleartextID_HARDCHECK. If the reflection doesn't stick in your environment, use the getCleartextID_SIMCHECK method instead, but take in consideration it should be adapted to your specific SIM-presence needs.

    P.S.: Do please note that OEM's have managed to bug out SERIAL against Google policy (multiple devices with same SERIAL), and Google as stated there is at least one known case in a big OEM (not disclosed and I don't know which brand it is either, I'm guessing Samsung).

    Disclaimer: This answers the original question of getting a unique device ID, but the OP introduced ambiguity by stating he needs a unique ID for an APP. Even if for such scenarios Android_ID would be better, it WILL NOT WORK after, say, a Titanium Backup of an app through 2 different ROM installs (can even be the same ROM). My solution maintains persistence that is independent of a flash or factory reset, and will only fail when IMEI or SERIAL tampering occurs through hacks/hardware mods.

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

    0 讨论(0)
  • 2020-11-22 14:27
    String deviceId = Settings.System.getString(getContentResolver(),
                                    Settings.System.ANDROID_ID);
    

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

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