Android: How To Programmatically Access The Device Serial Number Shown In The AVD Manager (API Version 8)


Answer :

This is the hardware serial number. To access it on

  • Android Q (>= SDK 29) android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required. Only system apps can require this permission. If the calling package is the device or profile owner then the READ_PHONE_STATE permission suffices.

  • Android 8 and later (>= SDK 26) use android.os.Build.getSerial() which requires the dangerous permission READ_PHONE_STATE. Using android.os.Build.SERIAL returns android.os.Build.UNKNOWN.

  • Android 7.1 and earlier (<= SDK 25) and earlier android.os.Build.SERIAL does return a valid serial.

It's unique for any device. If you are looking for possibilities on how to get/use a unique device id you should read here.

For a solution involving reflection without requiring a permission see this answer.


Up to Android 7.1 (SDK 25)

Until Android 7.1 you will get it with:

Build.SERIAL 

From Android 8 (SDK 26)

On Android 8 (SDK 26) and above, this field will return UNKNOWN and must be accessed with:

Build.getSerial() 

which requires the dangerous permission android.permission.READ_PHONE_STATE.

From Android Q (SDK 29)

Since Android Q using Build.getSerial() gets a bit more complicated by requiring:

android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE (which can only be acquired by system apps), or for the calling package to be the device or profile owner and have the READ_PHONE_STATE permission. This means most apps won't be able to uses this feature. See the Android Q announcement from Google.

See Android SDK reference


Best Practice for Unique Device Identifier

If you just require a unique identifier, it's best to avoid using hardware identifiers as Google continuously tries to make it harder to access them for privacy reasons. You could just generate a UUID.randomUUID().toString(); and save it the first time it needs to be accessed in e.g. shared preferences. Alternatively you could use ANDROID_ID which is a 8 byte long hex string unique to the device, user and (only Android 8+) app installation. For more info on that topic, see Best practices for unique identifiers.


Build.SERIAL can be empty or sometimes return a different value (proof 1, proof 2) than what you can see in your device's settings.

If you want a more complete and robust solution, I've compiled 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; } 

I try to update the gist regularly whenever I can test on a new device or Android version. Contributions are welcome too.


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?