53

I am developing an android application that targets Android 4.0 (API 14) and above.

I am looking for a serial number that is unique per device and that persists for ever (dies with the device, does not change after factory resets).

I have found lots of results on the web concerning unique identifiers for android devices, but very little on the android.os.Build.SERIAL number.

So far, I eliminated the use of the ANDROID_ID because it might change after factory resets. I also eliminated the use of the IMEI because the android device might be non-phone. I cannot use the wifi or bluetooth MAC ADDRESS because the device might not have such hardware and/or such mac addresses might not be readable if the hardware is not enabled (based on what I found on the web).

I believe I might go for the android device serial number.

It is easily accessible using android.os.Build.SERIAL (since it is added in API level 9 and does not need any additional permission).

My questions are :

  • Taking into consideration that my application targets Android 4.0 (API 14) and above, is the android.os.Build.SERIAL number for the android devices unique for each device ?

  • Currently, documentation of android.os.Build.SERIAL indicates : A hardware serial number, if available. Alphanumeric only, case-insensitive. Does this mean that the serial number might not be available ?

  • What could be another alternative that meets the conditions mentioned above ?

Leeeeeeelo
  • 4,333
  • 3
  • 34
  • 44

4 Answers4

56

Taking into consideration that my application targets Android 4.0 (API 14) and above, is the android.os.Build.SERIAL number for the android devices unique for each device ?

According to this useful article in the Android Developers blog, android.os.Build.SERIAL should be unique if it is available. From the article:

Devices without telephony are required to report a unique device ID here; some phones may do so also.

Does this mean that the serial number might not be available ?

Correct, it may not be available. Notice that they say "Devices without telephony are required...", so only devices without "telephony" (like wifi only tablets) are required to supply a SERIAL number, although some phones still do (like the Nexus 4).

Documentation is definitely lacking on this topic, but from the wording it's possible that only "devices without telephony" are required to submit a unique ID, while phones that do submit one might not be unique.

What could be another alternative that meets the conditions mentioned above ?

For your situation I think your best bet is to first check for a deviceId (IMEI, or what not) and if deviceId doesn't exist then you fallback to using android.os.Build.SERIAL (since this is probably a tablet) like so:

public static String getDeviceId(Context context) {
    final String deviceId = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
    if (deviceId != null) {
        return deviceId;
    } else {
        return android.os.Build.SERIAL;
    }
}

Keep in mind to use deviceId you need the permission android.permission.READ_PHONE_STATE.

So since your app's minSDK is 14, you can safely use the field android.os.Build.SERIAL. And if we assume that devices without telephony truly do always provide unique ids in SERIAL then I think this would be a safe bet on always getting a unique device id (bar any bugs of course).

José Cabo
  • 6,149
  • 3
  • 28
  • 39
Tony Chan
  • 8,017
  • 4
  • 50
  • 49
  • So if I use `Build.SERIAL` for devices that are not cell phones, and `getDeviceId()` for devices that are cell phones, do you think this would always work and always provide uniqueness? Thanks in advance. – LuckyMe Jul 14 '13 at 00:45
  • @LuckyMe If everything worked accordingly I think it would be safe. But of course there are bugs, for example, the article states for `getDeviceId()` _Bugs: We have seen a few instances of production phones for which the implementation is buggy and returns garbage, for example zeros or asterisks._ It also depends on what your min API will be, since `Build.SERIAL` is only available from API 9 and up. But if your situation is similar to the OP's then I think you are safe. But you should check your database anyway to see if you are getting weird device identifiers returned. – Tony Chan Jul 30 '13 at 21:47
  • 1
    I had been using Build.SERIAL thinking it was unique, but we just received a batch of tablets/phablets (API 15) from a manufacturer in China and the serial is the same on multiple devices (but not all). This maybe just a rogue manufacturer but I would recommend you not to rely on the serial being unique! – Peconia Mar 10 '16 at 15:28
  • 1
    ~"**although some phones still do**". Actually, MOST phones supply a serial number. Even the low-end prepaid phones do. You can query the serial number with `android.os.Build.SERIAL`. – IgorGanapolsky Sep 12 '16 at 14:20
11

I personally use Secure.ANDROID_ID & Build.SERIAL to identify a phone:

androidId = Settings.Secure.getString(this.getContentResolver(), 
                Settings.Secure.ANDROID_ID) + Build.SERIAL;

They may have the same ANDROID_ID, they may not have a SERIAL. But the chance of both is low.

fawaad
  • 341
  • 6
  • 12
Kai Wang
  • 3,303
  • 1
  • 31
  • 27
  • 2
    Seems it's a solution. I need some static unique string of every device to send to my server api to register an user. And it solution doesn't need any addon permissions. Like it! – Trancer Dec 12 '16 at 12:23
  • 3
    The problem is that the value you get using `Secure.ANDROID_ID` may change if the user does a factory reset, which means your concatenated ID will change too, even if it's still the same device. – Mickäel A. Sep 14 '17 at 13:22
5

You appear to have summarized the situation pretty well.

The serial number is intended to be unique for each device, but (this being Android) there are of course bugs that create exceptions, e.g. https://code.google.com/p/android/issues/detail?id=35193

As you point out, the docs suggest that this is intended to be a hardware serial number, but the way it is worded suggests that you shouldn't count on that. And don't mistake that for the device's actual serial number, i.e. the serial number printed on the back or on the box. As well, I believe it is much less widely used than android_id, so there could well be issues that are not reported.

I've seen it widely reported that the android_id is based on the serial number, but I believe that is not true - I recently observed that, on a tablet with the new multi-user capability, each user account gets its own android_id but the serial number is the same for both.

AFAIK 'another alternative' does not exist: your list is complete. The serial number is the closest thing to what you are after unless you are prepared to depend on wifi or bluetooth permissions.

Tom
  • 17,103
  • 8
  • 67
  • 75
  • 3
    You're correct that `android_id` is not based on the serial number. Apparently it's simply based off a random number generator. See the code changes they made [here](https://android.googlesource.com/platform/frameworks/base/+/9bb4ec484b9b9518bf5b17484dcb50727c58b5d1%5E%21/#F0) when they finally fixed the bug where a lot of devices had the same `android_id`. – Tony Chan Jun 05 '13 at 00:30
  • What about using `Settings.Secure.ANDROID_ID`? Wouldn't that be more reliably unique than the serial number? – IgorGanapolsky Sep 12 '16 at 14:30
0

I usually get unique id's by doing an SHA1 hash of some unique string (company name usually) + imei (if no imei, mac address [wifi, bluetooth, etc]). This gives me unique id's that look the same, tend to be unique per device (not perfect if the MAC is changed/faked though).

Ryan Schultz
  • 109
  • 2
  • 4