为什么有access主键的作用ID了,还要用uniqueidentifier

解决java - Is there a unique Android device ID? - android-uniqueidentifier-java - ITkeyowrd
解决java - Is there a unique Android device ID?
Settings.Secure#ANDROID_ID returns the Android ID as an unique 64-bit hex string. import android.provider.Settings.S private String android_id
领取地址:
Do Android devices have a unique ID, and if so, what is a simple way to access it using Java?
3,189 7 22 57 asked May 7 '10 at 0:47
9,940 6 15 22 16 & If you're using
ANDROID_ID be sure to read
Jan 16 '13 at 8:16 3 &
May 24 '13 at 17:10 && & I found perfect:
Apr 25 '14 at 5:00 && & I found this very helpful as it discusses all the available unique identifiers and weighs in each and concludes the best
Aug 31 '15 at 5:58
36 Answers 36
returns the Android ID as an
64-bit hex string.
import android.provider.Settings.S
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
Update: 06/05/2015
When reviewing this as a possible solution, please consider
below instead as an alternative.
? 1 1 answered May 7 '10 at 0:49
57k 12 99 106 328 & It's known to be null sometimes, it's documented as &can change upon factory reset&. Use at your own risk, and it can be easily changed on a rooted phone. –&
Jun 23 '10 at 14:21 23 &
Nov 27 '10 at 9:57 10 & I think we need to be careful about using ANDROID_ID in hash in first answer about because it may not be set when app is first run, may be set later, or may even change in theory, hence unique ID may change –& user604363 Feb 5 '11 at 17:06 36 & Be aware there are huge limitations with this solution:
Apr 7 '11 at 20:10 16 & ANDROID_ID no longer uniquely identifies a device (as of 4.2):
Dec 15 '12 at 19:36
UPDATE: As of recent versions of Android, many of the issues with ANDROID_ID have been resolved, and I believe this approach is no longer necessary. Please take a look at .
Full disclosure: my app that the below approach was originally used in no longer uses this approach, and we now use the approach outlined in the
entry that
links to (namely, generating and saving a ).
There are many answers to this question, most of which will only work &some& of the time, and unfortunately that's not good enough.
Based on my tests of devices (all phones, at least one of which is not activated):
All devices tested returned a value for TelephonyManager.getDeviceId()
All GSM devices (all tested with a SIM) returned a value for TelephonyManager.getSimSerialNumber()
All CDMA devices returned null for getSimSerialNumber() (as expected)
All devices with a Google account added returned a value for ANDROID_ID
All CDMA devices returned the same value (or derivation of the same value) for both ANDROID_ID and TelephonyManager.getDeviceId() -- as long as a Google account has been added during setup.
I did not yet have a chance to test GSM devices with no SIM, a GSM device with no Google account added, or any of the devices in airplane mode.
So if you want something unique to the device itself, TM.getDeviceId() should be sufficient. Obviously some users are more paranoid than others, so it might be useful to hash 1 or more of these identifiers, so that the string is still virtually unique to the device, but does not explicitly identify the user's actual device. For example, using String.hashCode(), combined with a UUID:
final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = && + tm.getDeviceId();
tmSerial = && + tm.getSimSerialNumber();
androidId = && + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() && 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
might result in something like: b3-e7c7-bffd97
It works well enough for me.
As Richard mentions below, don't forget that you need permission to read the TelephonyManager properties, so add this to your manifest:
&uses-permission android:name=&android.permission.READ_PHONE_STATE& /&
import libs
import android.content.C
import android.telephony.TelephonyM
import android.view.V
? 1 1 answered May 17 '10 at 22:12
34.6k 10 35 54 121 & Telephony-based ID won't be there on tablet devices, neh? –&
Jun 23 '10 at 14:27 19 & Hence why I said most won't work all the time :) I've yet to see any answer to this question that is reliable for all devices, all device types, and all hardware configurations. That's why this question is here to begin with. It's pretty clear that there is no end-all-be-all solution to this. Individual device manufacturers may have device serial numbers, but those are not exposed for us to use, and it is not a requirement. Thus we're left with what is available to us. –&
Jun 29 '10 at 19:40 26 & The code sample works great. Remember to add
&uses-permission android:name=&android.permission.READ_PHONE_STATE& /& to the manifest file. If storing in a database, the returned string is 36 characters long. –&
Feb 27 '11 at 22:28 7 & Be aware there are huge limitations with this solution:
Apr 7 '11 at 20:09 14 & @softarn: I believe what you're referring to is the Android Developer Blog that emmby already linked to, which explains what you are
trying to say, so perhaps you should have simply upvoted his comment instead. Either way, as emmby mentions in his answer, there are still problems even with the blog info. The question asks for a unique
DEVICE identifier (not installation identifier), so I disagree with your statement. The blog is making an assumption that what you want
is not necessarily to track the device, whereas the question asks for just that. I agree with the blog otherwise. –&
Jul 22 '11 at 0:45
Last Updated: 6/2/15
After reading every Stack Overflow post about creating a unique ID, the Google developer blog and Android documentation, I feel as if the 'Pseudo ID' is the best possible option.
Main Issue: Hardware vs Software
User's can change their hardware, Android tablet or phone, so unique IDs based on hard are not good ideas for TRACKING USERS
For TRACKING HARDWARE, this is a great idea
User's can wipe/change their ROM if they are rooted
You can track users across platforms(iOS, Android, Windows and Web)
The best want to TRACK AN INDIVIDUAL USER with their consent is to simply have them login(make this seamless using OAuth)
Overall breakdown with Android
- Guarantee uniqueness (include rooted devices) for API =& 9/10 (99.5% of Android devices)
- No extra permissions
Psuedo code:
if API =& 9/10: (99.5% of devices)
return unique ID containing serial id (rooted devices may be different)
return unique ID of build information (may overlap data - API & 9)
Thanks to @stansult for posting
(in this Stack Overflow question).
List of options - reasons why/ why not to use them:
User Email - Software
User could change email - HIGHLY unlikely
API 5+ &uses-permission android:name=&android.permission.GET_ACCOUNTS& /& or
API 14+ &uses-permission android:name=&android.permission.READ_PROFILE& /& &uses-permission android:name=&android.permission.READ_CONTACTS& /& ()
User Phone Number - Software
Users could change phone numbers - HIGHLY unlikely
&uses-permission android:name=&android.permission.READ_PHONE_STATE& /&
IMEI - Hardware (only phones, needs android.permission.READ_PHONE_STATE)
Most users hate the fact that it says &Phone Calls& in the permission. Some users give bad ratings, because they believe you are simply stealing their personal information, when all you really want to do is track device installs. It is obvious that you are collecting data.
&uses-permission android:name=&android.permission.READ_PHONE_STATE& /&
Android ID - Hardware (can be null, can change upon factory reset, can be altered on a rooted device)
Since it can be 'null', we can check for 'null' and change its value, but this means it will no longer be unique.
If you have a user with a factory reset device, the value may have changed or altered on the rooted device so there may be duplicates entries if you are tracking user installs.
WLAN MAC Address - Hardware (needs android.permission.ACCESS_WIFI_STATE)
This could be the second best option, but you are still collecting and storing a unique identifier that comes directly from a user. This is obvious that you are collecting data.
&uses-permission android:name=&android.permission.ACCESS_WIFI_STATE &/&
Bluetooth MAC Address - Hardware (devices with Bluetooth, needs android.permission.BLUETOOTH)
Most applications on the market do not use Bluetooth, and so if your application doesn't use Bluetooth and you are including this, the user could become suspicious.
&uses-permission android:name=&android.permission.BLUETOOTH &/&
Pseudo-Unique ID - Software (for all Android devices)
Very possible, may contain collisions - See my method posted below!
This allows you to have an 'almost unique' ID from the user without taking anything that is private. You can create you own unanimous ID from device information.
I know there isn't any 'perfect' way of getting a unique ID witho however, sometimes we only really need to do is track the device installation. When it comes to creating a unique ID, we can create a 'pseudo unique id' based solely off of information that the Android API gives us without using extra permissions. This way, we can show the user respect and try to offer a good user experience as well.
With a pseudo-unique id, you really only run into the fact that there may be duplicates based on the fact that there are similar devices. You can tweak the combined method to however, some developers need to track device installs and this will do the trick or performance based on similar devices.
If their Android device is API 9 or over, this is guaranteed to be unique because of the 'Build.SERIAL' field.
REMEMBER, you are technically only missing out on around 0.5% of users . So you can focus on the rest: This is 99.5% of the users!
If the user's Android device is lower than API 9; hopefully, they have not done a factory reset and their 'Secure.ANDROID_ID' will be preserved or not 'null'. (see )
If all else fails:
If all else fails, if the user does have lower than API 9 (lower than Gingerbread), has reset their device or 'Secure.ANDROID_ID' returns 'null', then simply the ID returned will be solely based off their Android device information. This is where the collisions can happen.
Removed 'Android.SECURE_ID' because of factory resets could cause the value to change
Edited the code to change on API
Changed the Pseudo
Please take a look at the method below:
* Return pseudo unique ID
* @return ID
public static String getUniquePsuedoID() {
// If all else fails, if the user does have lower than API 9 (lower
// than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
// returns 'null', then simply the ID returned will be solely based
// off their Android device information. This is where the collisions
// can happen.
// Thanks http://www.pocketmagic.net/?p=1662!
// Try not to use DISPLAY, HOST or ID - these items could change.
// If there are collisions, there will be overlapping data
String m_szDevIDShort = &35& + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// Thanks to @Roman SL!
// https://stackoverflow.com/a/427
// Only devices with API &= 9 have android.os.Build.SERIAL
// http://developer.android.com/reference/android/os/Build.html#SERIAL
// If a user upgrades software or roots their device, there will be a duplicate entry
String serial =
serial = android.os.Build.class.getField(&SERIAL&).get(null).toString();
// Go ahead and return the serial for api =& 9
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
// String needs to be initialized
serial = &serial&; // some value
// Thanks @Joe!
// https://stackoverflow.com/a/427
// Finally, combine the values we have found by using the UUID class to create a unique identifier
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
New(for apps with ads AND Google Play Services):
From the Google Play Developer's console:
Beginning August 1st, 2014, the Google Play Developer Program Policy requires all new app uploads and updates to use the advertising ID in lieu of any other persistent identifiers for any advertising purposes. Learn more
Implementation:
Permission:
&uses-permission android:name=&android.permission.INTERNET& /&
import com.google.android.gms.ads.identifier.AdvertisingIdC
import com.google.android.gms.ads.identifier.AdvertisingIdClient.I
import com.google.android.gms.common.GooglePlayServicesAvailabilityE
import com.google.android.gms.common.GooglePlayServicesNotAvailableE
import java.io.IOE
// Do not call this function from the main thread. Otherwise,
// an IllegalStateException will be thrown.
public void getIdThread() {
Info adInfo =
adInfo = AdvertisingIdClient.getAdvertisingIdInfo(mContext);
} catch (IOException exception) {
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesAvailabilityException exception) {
// Encountered a recoverable error connecting to Google Play services.
} catch (GooglePlayServicesNotAvailableException exception) {
// Google Play services is not available entirely.
final String id = adInfo.getId();
final boolean isLAT = adInfo.isLimitAdTrackingEnabled();
Source/Docs:
Important:
It is intended that the advertising ID completely replace existing usage of other identifiers for ads purposes (such as use of ANDROID_ID in Settings.Secure) when Google Play Services is available. Cases where Google Play Services is unavailable are indicated by a GooglePlayServicesNotAvailableException being thrown by getAdvertisingIdInfo().
Warning, users can reset:
I have tried to reference every link that I took information from. If you are missing and need to be included, please comment!
Google Player Services InstanceID
? 1 1 answered Jul 12 '13 at 23:58
30k 15 99 131 1 & i used your method in my app for sending comments. i have bad news. unfortunately PsuedoID isn't unique completely. my server recorded more than 100 for 5 ID and more than 30 for almost 30 ID. the most repeated IDs are 'ffffffff-fc8f-6093-ffff-ffffd8' (159 record) and 'ffffffff-fe99-b334-ffff-ffffef' (154 time). also based on time and comments it's obvious there are different peoples. the total records until now is 10,000. please let me know why this happened. tanks. –&
Mar 17 '15 at 16:36 1 & I wrote this 1.5+ years ago. I am not sure why it is not unique for you. You can try the advertising ID. If not, you can come up with your own solution. –&
Mar 17 '15 at 17:35 1 & sorta..I'd really appreciate if you go through the question and give your thoughts on this –&
Apr 29 '15 at 17:41 2 & @JaredBurrows: wow, that is one well-researched and thorough answer. It d-) –&
May 6 '15 at 10:00 2 & If I could +100 this I would, thanks for the in depth answer! –&
Jun 22 '15 at 14:38
As Dave Webb mentions, the
that covers this. Their preferred solution is to track app installs rather than devices, and that will work well for most use cases. The blog post will show you the necessary code to make that work, and I recommend you check it out.
However, the blog post goes on to discuss solutions if you need a device identifier rather than an app installation identifier. I spoke with someone at Google to get some additional clarification on a few items in the event that you need to do so. Here's what I discovered about device identifiers that's NOT mentioned in the aforementioned blog post:
ANDROID_ID is the preferred device identifier. 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 , which is . 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).
Note that for devices that have to fallback on the device ID, the unique ID WILL persist across factory resets. This is something to be aware of. If you need to ensure that a factory reset will reset your unique ID, you may want to consider falling back directly to the random UUID instead of the device ID.
Again, this code is for a device ID, not an app installation ID. For most situations, an app installation ID is probably what you're looking for. But if you do need a device ID, then the following code will probably work for you.
import android.content.C
import android.content.SharedP
import android.provider.Settings.S
import android.telephony.TelephonyM
import java.io.UnsupportedEncodingE
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 volatile static 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);
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
if (!&e549c&.equals(androidId)) {
uuid = UUID.nameUUIDFromBytes(androidId
.getBytes(&utf8&));
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
public UUID getDeviceUuid() {
10.9k 12 82 182 answered Apr 11 '11 at 19:06
57.2k 50 151 211 4 & Shouldn't you be hashing the various IDs so that they're all the same size? Additionally, you should be hashing the device ID in order to not accidentally expose private information. –&
Apr 11 '11 at 20:10 1 & Good points, Steve. I updated the code to always return a UUID. This ensure that a) the generated IDs are always the same size, and b) the android and device IDs are hashed before being returned to avoid accidentally exposing personal information. I also updated the description to note that device ID will persist across factory resets and that this may not be desirable for some users. –&
Apr 11 '11 at 21:53 1 & I belie the preferred solution is to track installations, not device identifiers. Your code is substantially longer and more complex than that in the blog post and it's not obvious to me that it adds any value. –&
Apr 12 '11 at 4:58 7 & Good point, I updated the commentary to strongly suggest users use app installation ids rather than device ids. However, I think this solution is still valuable for people who do need a device rather than installation ID. –&
Apr 12 '11 at 12:25 8 & ANDROID_ID can change on factory reset, so it cannot identify devices as well –&
May 19 '11 at 8:12
Here is the code that Reto Meier used in the
presentation this year to get a unique id for the user:
private static String uniqueID =
private static final String PREF_UNIQUE_ID = &PREF_UNIQUE_ID&;
public synchronized static String id(Context context) {
if (uniqueID == null) {
SharedPreferences &dPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = &dPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = &dPrefs.edit();
editor.putString(PREF_UNIQUE_ID, uniqueID);
editor.commit();
return uniqueID;
If you couple this with a backup strategy to send preferences to the cloud (also described in Reto's , you should have an id that ties to a user and sticks around after the device has been wiped, or even replaced. I plan to use this in analytics going forward (in other words, I have not done that bit yet :).
11.2k 16 76 109 answered Oct 28 '11 at 13:19
1,906 1 9 12 7 & Great answer, this should go the top. –&
Dec 16 '11 at 5:13 && & I was using @Lenn Dolling's method with current time appended for unique id. But this seems like more simpler and reliable way. Thanks Reto Meier and Antony Nolan –&
Jan 3 '12 at 13:55 2 & Great option if you don't need the unique ID to persist after an uninstall and reinstall (e.g. promotional event/game where you get three chances to win, period). –&
May 15 '12 at 21:52 2 & The Meier presentation relies upon using the Android Backup Manager, which in turn depends upon the user choosing to turn that feature on. That is fine for app user preferences (Meier's use), because if the user has not selected that option, she just won't get those backed up. However, the original question is about generating a unique ID for the
device, and this ID is generated per app, and not even per installation, let alone per device, and since it relies upon the user selecting the backup option, its uses beyond user preferences (e.g., for a time-limited trial) are limited. –&
Dec 22 '12 at 11:15 9 & This won't work on an uninstall or clearing of data. –&
Sep 2 '14 at 2:25
Also you might consider the Wi-Fi adapter's MAC address. Retrieved thusly:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Requires permission android.permission.ACCESS_WIFI_STATE in the manifest.
Reported to be available even when Wi-Fi is not connected. If Joe from the answer above gives this one a try on his many devices, that'd be nice.
On some devices, it's not available when Wi-Fi is turned off.
NOTE: From Android 6.x, it returns consistent fake mac address: 02:00:00:00:00:00
27.3k 9 76 153 answered Jun 23 '10 at 14:27
41.4k 14 105 199 8 & This required
android.permission.ACCESS_WIFI_STATE –&
Nov 1 '10 at 4:41 7 & They exist? I'd rather envision a telephony-less device (AKA tablet)... –&
Dec 22 '10 at 14:23 4 & I know this question is old - but this is a great idea. I used the BT mac ID in my app, but only because it requires BT to function. Show me an Android device that's worth developing for that does NOT have WiFi. –&
Aug 29 '11 at 21:27 5 & I think you'll find that it's unavailable when WiFi is off, on pretty much all android devices. Turning WiFi off removes the device at kernel level. –&
May 21 '12 at 23:38 10 & @Sanandrea - let's face it, on a rooted device EVERYTHING can be spoofed. –&
Sep 4 '13 at 9:53
There’s rather useful info .
It covers five different ID types:
IMEI (only for Android devices with P needs android.permission.READ_PHONE_STATE)
Pseudo-Unique ID (for all Android devices)
Android ID (can be null, can change upon factory reset, can be altered on rooted phone)
WLAN MAC Address string (needs android.permission.ACCESS_WIFI_STATE)
BT MAC Address string (devices with Bluetooth, needs android.permission.BLUETOOTH)
answered Feb 8 '12 at 2:16
987 8 17 1 & Important point left out (here and in article): you can't get WLAN or BT MAC unless they are turned on! Otherwise I think the WLAN MAC would be the perfect identifier. You have no guarantee that the user will ever turn on their Wi-Fi, and I don't really think it is 'appropriate' to turn it on yourself. –&
Oct 7 '12 at 22:44 1 & @Tom you're wrong. You can still read WLAN or BT MAC even when they're turned off. However, there is no guarantee that the device has WLAN or BT modules available. –&
Aug 4 '14 at 10:20 && & Most notably, Local WiFi and Bluetooth MAC addresses are no longer available.The getMacAddress() method of aWifiInfo object and the BluetoothAdapter.getDefaultAdapter().getAddress() method will both return02:00:00:00:00:00 from now on –&
Mar 30 '16 at 6:03 2 & @sarikakate It is true only in 6.0 Marshmallow and above... It is still working as expected in below 6.0 Marshmallow. –&
Apr 13 '16 at 10:22 && & @Smeet Yeah you are right.I forgot to mention that its working below 6.0 –&
Apr 14 '16 at 4:15
The official Android Developers Blog now has a full article just about this very subject, .
11.2k 16 76 109 answered Apr 6 '11 at 7:36
7,307 4 48 46 3 & And the key point of that argument is that if you're trying to get a unique ID out of the hardware, you're probably making a mistake. –&
Apr 12 '11 at 4:57 3 & And if you're allowing your device-lock to be reset by a factory reset, your trialware model is as good as dead. –&
May 4 '11 at 18:54
Reto Meier released a robust answer to how to approach this which should meet most developers needs to track users across installations. Anthony Nolan shows the direction in his answer, but I thought I'd write out the full approach so that others can easily see how to do it (it took me a while to figure out the details).
This approach will give you an anonymous, secure user ID which will be persistent for the user across different devices (based on the primary Google account) and across installs. The basic approach is to generate a random user ID and to store this in the apps' &d preferences. You then use Google's backup agent to store the &d preferences linked to the Google account in the cloud.
Let's 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 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 &dpreferences:
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
public void onCreate() {
SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,
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 =
private static final String PREF_UNIQUE_ID = &PREF_UNIQUE_ID&;
if (uniqueID == null) {
SharedPreferences &dPrefs = context.getSharedPreferences(
MyBackupAgent.PREFS, Context.MODE_PRIVATE);
uniqueID = &dPrefs.getString(PREF_UNIQUE_ID, null);
if (uniqueID == null) {
uniqueID = UUID.randomUUID().toString();
Editor editor = &dPrefs.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 moves device.
For more information on this approach see .
And for full details of how to implement the backup agent see . 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.
11.2k 16 76 109 answered Dec 22 '12 at 8:13
1,132 13 24 2 & Doesn't this lead to multiple devices with the same id when a user has multiple devices? A tablet and a phone for instance. –&
Mar 13 '13 at 2:25 && & Minimum target 8 is required for this. –&
Apr 3 '13 at 17:24 && & Would this be the preferred way to create a verification payload when doing in-app purchases? From In-app billing example code comment: &So a good developer payload has these characteristics: 1. If two different users purchase an item, the payload is different between them, so that one user's purchase can't be replayed to another user. 2. The payload must be such that you can verify it even when the app wasn't the one who initiated the purchase flow (so that items purchased by the user on one device work on other devices owned by the user).& –&
Aug 14 '13 at 7:02 && & @Tosa I had just the same question. But couldn't we use this same technique again to create virtual device ids and just not back that up the same way? The device id would not persist past a wipe or reinstall but if we have a persistent user id we might not need that much from a device id. –&
May 19 '16 at 7:03
The following code returns the device serial number using a hidden Android API. But, this code don't works on Samsung Galaxy Tab because &ro.serialno& isn't set on this device.
String serial =
Class&?& c = Class.forName(&android.os.SystemProperties&);
Method get = c.getMethod(&get&, String.class);
serial = (String) get.invoke(c, &ro.serialno&);
catch (Exception ignored) {
11.2k 16 76 109 answered Jan 25 '11 at 2:39
647 7 4 && & I just read on xda developer that the
ro.serialno is used to generate the
Settings.Secure.ANDROID_ID. So they are basically different representations of the same value. –&
Jun 23 '11 at 6:31 && & @Martin: but probably serial number doesn't change on resetting the device. Isn't it? Just a new value for
ANDROID_ID is derived from it. –&
Sep 17 '11 at 8:28 && & Actually on all devices I have tested they where the identical same. Or at least the hash values where the same (for privacy reasons I do not write the true values to the log files). –&
Sep 18 '11 at 11:53 && & that use a native_get method, and there is a set too:
–& user529543 Oct 14 '13 at 17:56 && & This value is the same as
android.os.Build.SERIAL –&
Mar 8 at 10:25
I think this is sure fire way of building a skeleton for a unique ID... check it out.
Pseudo-Unique ID, that works on all Android devices Some devices don't have a phone (eg. Tablets) or for some reason you don't want to include the READ_PHONE_STATE permission. You can still read details like ROM Version, Manufacturer name, CPU type, and other hardware details, that will be well suited if you want to use the ID for a serial key check, or other general purposes. The ID computed in this way won't be unique: it is possible to find two devices with the same ID (based on the same hardware and rom image) but the chances in real world applications are negligible. For this purpose you can use the Build class:
String m_szDevIDShort = &35& + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
Most of the Build members are strings, what we're doing here is to take their length and transform it via modulo in a digit. We have 13 such digits and we are adding two more in front (35) to have the same size ID like the IMEI (15 digits). There are other possibilities here are well, just have a look at these strings. Returns something like: 247 . No special permission are required, making this approach very convenient.
(Extra info: The technique given above was copied from an article on .)
42k 15 65 81 answered Mar 24 '11 at 19:55
978 10 17 7 & Interesting solution. It sounds like this is a situation where you really should be just hashing all that data concatenated instead of trying to come up with your own &hash& function. There are many instances where you'd get collisions even if there is substantial data that is different for each value. My recommendation: use a hash function and then transform the binary results into decimal and truncate it as needed. To do it right, though you should really use a UUID or full hash string. –&
Apr 12 '11 at 16:28 13 & You should give credit to your sources... This has been lifted straight out of the following article:
May 16 '11 at 12:07 7 & This ID is open to collisions like you don't know what. It's practically guaranteed to be the same on identical devices from the same carrier. –&
May 26 '11 at 20:21 5 & This may also change if the device gets upgraded. –&
Jan 25 '12 at 12:25 3 & I don't think it's good idea to use this solution. As I understand all Build fields will be the same for all phones produced together. –&
Jul 26 '12 at 17:26
Using the code below, you can get the unique device ID of an Android OS device as a string.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
11.2k 16 76 109 answered May 17 '11 at 14:44
5,345 7 19 41
field was added to the Build class in API level 9 (Android 2.3 - Gingerbread). Documentation says it represents the hardware serial number. Thus it should be unique, if it exists on the device.
I don't know whether it is actually supported (=not null) by all devices with API level &= 9 though.
11.2k 16 76 109 answered Mar 6 '11 at 15:28
3,001 1 23 42 2 & Unfortunately, it's &unknown&. –&
Apr 15 '13 at 12:33
One thing I'll add - I have one of those unique situations.
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
Turns out that even though my Viewsonic G Tablet reports a DeviceID that is not Null, every single G Tablet reports the same number.
Makes it interesting playing &Pocket Empires& which gives you instant access to someone's account based on the &unique& DeviceID.
My device does not have a cell radio.
answered Mar 21 '11 at 20:46
1,296 12 13 && & What is the id ? is it perchance
e549c ? –&
Sep 18 '13 at 13:44 && & Wow that was so long ago I've long since tossed that tablet. Couldn't say. –&
Sep 25 '13 at 19:36 && & The above mentioned solution is fine. is it Android secureid changing after update the os version?.. like current 5.0.. after updated 5.1 or 6.0 .. The above mentioned id same or difference ? –&
Apr 18 at 9:43
For detailed instructions on how to get a unique identifier for each Android device your application is installed from, see the official Android Developers Blog posting .
It seems the best way is for you to generate one yourself upon installation and subsequently read it when the application is re-launched.
I personally find this acceptable but not ideal. No one identifier provided by Android works in all instances as most are dependent on the phone's radio states (Wi-Fi on/off, cellular on/off, Bluetooth on/off). The others, like Settings.Secure.ANDROID_ID must be implemented by the manufacturer and are not guaranteed to be unique.
The following is an example of writing data to an installation file that would be stored along with any other data the application saves locally.
public class Installation {
private static String sID =
private static final String INSTALLATION = &INSTALLATION&;
public synchronized static String id(Context context) {
if (sID == null) {
File installation = new File(context.getFilesDir(), INSTALLATION);
if (!installation.exists())
writeInstallationFile(installation);
sID = readInstallationFile(installation);
catch (Exception e) {
throw new RuntimeException(e);
return sID;
private static String readInstallationFile(File installation) throws IOException {
RandomAccessFile f = new RandomAccessFile(installation, &r&);
byte[] bytes = new byte[(int) f.length()];
f.readFully(bytes);
f.close();
return new String(bytes);
private static void writeInstallationFile(File installation) throws IOException {
FileOutputStream out = new FileOutputStream(installation);
String id = UUID.randomUUID().toString();
out.write(id.getBytes());
out.close();
11.2k 16 76 109 answered Aug 2 '11 at 3:21
8,891 15 58 89 && & If you want to track app installations this is perfect. Tracking devices though is a lot trickier, and there doesn't appear to be a completely air-tight solution. –&
Oct 3 '11 at 19:56 && & What about rooted devices? They can change this installation id easily, right? –&
May 9 '12 at 21:24 && & Absolutely. Root can change the installation ID. You can check for root using this code block:
May 18 '12 at 16:52 && & if we reset factory, will the file delete? –&
Jan 8 '15 at 10:26 && & If you factory reset and delete or format the /data partition the UUID is different. –&
Jan 12 '15 at 2:08
Add Below code in class file:
final TelephonyManager tm = (TelephonyManager) getBaseContext()
.getSystemService(SplashActivity.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = && + tm.getDeviceId();
Log.v(&DeviceIMEI&, && + tmDevice);
tmSerial = && + tm.getSimSerialNumber();
Log.v(&GSM devices Serial Number[simcard] &, && + tmSerial);
androidId = && + android.provider.Settings.Secure.getString(getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
Log.v(&androidId CDMA devices&, && + androidId);
UUID deviceUuid = new UUID(androidId.hashCode(),
((long) tmDevice.hashCode() && 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
Log.v(&deviceIdUUID universally unique identifier&, && + deviceId);
String deviceModelName = android.os.Build.MODEL;
Log.v(&Model Name&, && + deviceModelName);
String deviceUSER = android.os.Build.USER;
Log.v(&Name USER&, && + deviceUSER);
String devicePRODUCT = android.os.Build.PRODUCT;
Log.v(&PRODUCT&, && + devicePRODUCT);
String deviceHARDWARE = android.os.Build.HARDWARE;
Log.v(&HARDWARE&, && + deviceHARDWARE);
String deviceBRAND = android.os.Build.BRAND;
Log.v(&BRAND&, && + deviceBRAND);
String myVersion = android.os.Build.VERSION.RELEASE;
Log.v(&VERSION.RELEASE&, && + myVersion);
int sdkVersion = android.os.Build.VERSION.SDK_INT;
Log.v(&VERSION.SDK_INT&, && + sdkVersion);
Add in AndroidManifest.xml:
&uses-permission android:name=&android.permission.READ_PHONE_STATE& /&
answered Feb 27 '13 at 10:03
1,991 16 40
Adding to what others have said, there is a new Best practices for unique identifiers guide in the official Android documentation:
answered Feb 5 '16 at 3:30
4,537 1 18 25 && & This is a good article. Well worth the read. –&
Mar 3 at 1:11
The unique device ID of an Android OS device as String, using TelephonyManager and ANDROID_ID, is obtained by:
String deviceId;
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null) {
deviceId = mTelephony.getDeviceId();
deviceId = Secure.getString(
getApplicationContext().getContentResolver(),
Secure.ANDROID_ID);
But I strongly recommend a method suggested by Google, see .
answered Jan 13 '14 at 0:30
66.6k 12 185 158
There are a lot of different approaches to work around those ANDROID_ID issues (may be null sometimes or devices of a specific model always return the same ID) with pros and cons:
Implementing a custom ID generation algorithm (based on device properties that are supposed to be static and won't change -& who knows)
Abusing other IDs like , serial number, Wi-Fi/Bluetooth-MAC address (they won't exist on all devices or additional permissions become necessary)
I myself prefer using an existing OpenUDID implementation (see ) for Android (see ). It is easy to integrate and makes use of the ANDROID_ID with fallbacks for those issues mentioned above.
11.2k 16 76 109 answered Nov 18 '12 at 10:26
4,419 2 15 15
How about the . That is unique for Android or other mobile devices.
answered Jul 14 '11 at 20:01
15.9k 10 73 103 7 & Not for my tablets, which don't have an IMEI since they don't connect to my mobile carrier. –&
Jan 5 '12 at 16:54 1 & Not to mention CDMA devices which have an ESN instead of an IMEI. –&
Jan 25 '12 at 12:25 && & @David Given is there any CDMA with Android? –&
Jan 26 '12 at 14:29 1 & It only will do that is it
is a telephone :) A Tablet may not. –&
Jan 26 '12 at 19:39 3 & @ElzoValugi It's &this days& already and still not all tablets have SIM cards. –&
Sep 25 '12 at 9:42
My two cents - NB this is for a device (err) unique ID - not the installation one as discussed in the .
Of note that the
provided by @emmby falls back in a per application ID as the SharedPreferences are not synchronized across processes (see
and ). So I avoided this altogether.
Instead, I encapsulated the various strategies for getting a (device) ID in an enum - changing the order of the enum constants affects the priority of the various ways of getting the ID. The first non-null ID is returned or an exception is thrown (as per good Java practices of not giving null a meaning). So for instance I have the TELEPHONY one first - but a good default choice would be the ANDROID_ID beta:
import android.Manifest.
import android.bluetooth.BluetoothA
import android.content.C
import android.content.pm.PackageM
import android.net.wifi.WifiM
import android.provider.Settings.S
import android.telephony.TelephonyM
import android.util.L
// TODO : hash
public final class DeviceIdentifier {
private DeviceIdentifier() {}
/** @see http://code.google.com/p/android/issues/detail?id=10603 */
private static final String ANDROID_ID_BUG_MSG = &The device suffers from &
+ &the Android ID bug - its ID is the emulator ID : &
+ IDs.BUGGY_ANDROID_ID;
private static volatile S // volatile needed - see EJ item 71
// need lazy initialization to get a context
* Returns a unique identifier for this device. The first (in the order the
* enums constants as defined in the IDs enum) non null identifier is
* returned or a DeviceIDException is thrown. A DeviceIDException is also
* thrown if ignoreBuggyAndroidID is false and the device has the Android ID
* @param ctx
an Android constant (to retrieve system services)
* @param ignoreBuggyAndroidID
if false, on a device with the android ID bug, the buggy
android ID is not returned instead a DeviceIDException is
* @return a *device* ID - null is never returned, instead a
DeviceIDException is thrown
* @throws DeviceIDException
if none of the enum methods manages to return a device ID
public static String getDeviceIdentifier(Context ctx,
boolean ignoreBuggyAndroidID) throws DeviceIDException {
String result =
if (result == null) {
synchronized (DeviceIdentifier.class) {
if (result == null) {
for (IDs id : IDs.values()) {
result = uuid = id.getId(ctx);
} catch (DeviceIDNotUniqueException e) {
if (!ignoreBuggyAndroidID)
throw new DeviceIDException(e);
if (result != null)
throw new DeviceIDException();
private static enum IDs {
TELEPHONY_ID {
String getId(Context ctx) {
// TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
final TelephonyManager tm = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
w(&Telephony Manager not available&);
assertPermission(ctx, permission.READ_PHONE_STATE);
return tm.getDeviceId();
ANDROID_ID {
String getId(Context ctx) throws DeviceIDException {
// no permission needed !
final String andoidId = Secure.getString(
ctx.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
if (BUGGY_ANDROID_ID.equals(andoidId)) {
e(ANDROID_ID_BUG_MSG);
throw new DeviceIDNotUniqueException();
return andoidId;
WIFI_MAC {
String getId(Context ctx) {
WifiManager wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (wm == null) {
w(&Wifi Manager not available&);
assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
// getMacAddress() has no java doc !!!
return wm.getConnectionInfo().getMacAddress();
BLUETOOTH_MAC {
String getId(Context ctx) {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
w(&Bluetooth Adapter not available&);
assertPermission(ctx, permission.BLUETOOTH);
return ba.getAddress();
// TODO PSEUDO_ID
// http://www.pocketmagic.net/2011/02/android-unique-device-id/
static final String BUGGY_ANDROID_ID = &e549c&;
private final static String TAG = IDs.class.getSimpleName();
abstract String getId(Context ctx) throws DeviceIDE
private static void w(String msg) {
Log.w(TAG, msg);
private static void e(String msg) {
Log.e(TAG, msg);
private static void assertPermission(Context ctx, String perm) {
final int checkPermission = ctx.getPackageManager().checkPermission(
perm, ctx.getPackageName());
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(&Permission & + perm + & is required&);
// =========================================================================
// Exceptions
// =========================================================================
public static class DeviceIDException extends Exception {
private static final long serialVersionUID = -4519417L;
private static final String NO_ANDROID_ID = &Could not retrieve a &
+ &device ID&;
public DeviceIDException(Throwable throwable) {
super(NO_ANDROID_ID, throwable);
public DeviceIDException(String detailMessage) {
super(detailMessage);
public DeviceIDException() {
super(NO_ANDROID_ID);
public static final class DeviceIDNotUniqueException extends
DeviceIDException {
private static final long serialVersionUID = -9484955L;
public DeviceIDNotUniqueException() {
super(ANDROID_ID_BUG_MSG);
? 1 1 answered Sep 18 '13 at 19:12
10.9k 12 82 182
For hardware recognition of a specific Android device you could check the MAC Addresses.
you can do it that way:
in AndroidManifest.xml
&uses-permission android:name=&android.permission.INTERNET& /&
now in your code:
List&NetworkInterface& interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
In every Android device their is at least a &wlan0& Interface witch is the WI-FI chip. This code works even when WI-FI is not turned on.
P.S. Their are a bunch of other Interfaces you will get from the list containing MACS But this can change between phones.
80 8 answered Sep 1 '15 at 12:32
Here is how I am generating the unique id:
public static String getDeviceId(Context ctx)
TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice = tm.getDeviceId();
String androidId = Secure.getString(ctx.getContentResolver(), Secure.ANDROID_ID);
String serial =
if(Build.VERSION.SDK_INT & Build.VERSION_CODES.FROYO) serial = Build.SERIAL;
if(tmDevice != null) return &01& + tmD
if(androidId != null) return &02& + androidId;
if(serial != null) return &03& +
// other alternatives (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)
answered May 27 '13 at 18:34
73.4k 46 208 315 && & if we user ReadPhoneState in 6.0 version asking for runtime permission –&
Nov 17 '16 at 14:06
Another way is to use /sys/class/android_usb/android0/iSerial in an app without any permissions whatsoever.
user@creep:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root
-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
Motorola Xoom 3G
Toshiba AT300
Mini MK802
Samsung Galaxy S II
You can also see my blog post
where I discuss what other files are available for information.
11.2k 16 76 109 answered Jan 31 '13 at 15:40
131 1 4 && & I just read your blog post. I believe that this is not unique: Build.SERIAL is also available w/o any permissions, and is (in theory) a unique hardware serial number. –&
Apr 30 '13 at 21:14 1 & You're right. It's just one more way that your device can be tracked, and as you said both of these ways require no app permissions. –&
Mar 14 '14 at 17:16
More specifically, Settings.Secure.ANDROID_ID. This is a 64-bit quantity that is generated and stored when the device first boots. It is reset when the device is wiped.
ANDROID_ID seems a good choice for a unique device identifier. There are downsides: First, it is not 100% reliable on releases of Android prior to 2.2 (“Froyo”). Also, there has been at least one widely-observed bug in a popular handset from a major manufacturer, where every instance has the same ANDROID_ID.
5,762 9 27 54 answered Jun 7 '16 at 3:35
79 1 3 && & this answer is a copypaste from the old google blog
. So the bug is already resolved? –&
Jan 27 at 11:22
I found a library on Github that seems to bundle a few of the approaches discussed in this thread:
Haven't tried it, but maybe it helps.
answered May 13 '15 at 14:04
Google Instance ID
Released at I/O 2015; on Android requires play services 7.5.
InstanceID iid = InstanceID.getInstance( context );
// Google docs are wrong - this requires context
String id = iid.getId();
// blocking call
It seems that Google intends for this ID to be used to identify installations across Android, Chrome, and iOS.
It identifies an installation rather then a device, but then again, ANDROID_ID (which is the 解决方法 answer) now no longer identifies devices either. With the ARC runtime a new ANDROID_ID is generated for every installation (), just like this new instance ID. Also, I think that identifying installations (not devices) is what most of us are actually looking for.
The advantages of instance ID
It appears to me that Google intends for it to be used for this purpose (identifying your installations), it is cross-platform, and can be used for a number of other purposes (see the links above).
If you use GCM, then you will eventually need to use this instance ID because you need it in order to get the GCM token (which replaces the old GCM registration ID).
The disadvantages/issues
In the current implementation (GPS 7.5) the instance ID is retrieved from a server when your app requests it. This means that the call above is a blocking call - in my unscientific testing it takes 1-3 seconds if the device is online, and 0.5 - 1.0 seconds if off-line (presumably this is how long it waits before giving up and generating a random ID). This was tested in North America on Nexus 5 with Android 5.1.1 and GPS 7.5.
If you use the ID for the purposes they intend - eg. app authentication, app identification, GCM - I think this 1-3 seconds could be a nuisance (depending on your app, of course).
? 1 1 answered Jun 19 '15 at 22:22
9,814 2 35 52 1 & another significant downside of instanceID is that a new instanceID will be generated for you if the user clears the data of the app. –&
Jul 8 '15 at 16:13 && & Interesting, but I don't think it really changes the potential use-cases: instance ID, like android_id, is not suited to identifying a device. So your server will see user clearing data as like user uninstalling and re-installing your app - which is not unreasonable. –&
Jul 8 '15 at 20:11
I use the following code to get the IMEI or use Secure.ANDROID_ID as an alternative, when the device doesn't have phone capabilities:
String identifier =
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE));
if (tm != null)
identifier = tm.getDeviceId();
if (identifier == null || identifier .length() == 0)
identifier = Secure.getString(activity.getContentResolver(),Secure.ANDROID_ID);
5,762 9 27 54 answered Apr 15 '13 at 13:01
8,371 8 68 91
There are 30+ answers here and some are same and some are unique. This answer is based on few of those answers. One of them being @Lenn Dolling's answer.
It combines 3 IDs and creates a 32-digit hex string. It has worked very well for me.
3 IDs are: Pseudo-ID - It is generated based on physical device specifications ANDROID_ID - Settings.Secure.ANDROID_ID Bluetooth Address - Bluetooth adapter address
It will return something like this: 551F27C30B0A0F
Note: You can always add more IDs to the longId string. For example, Serial #. wifi adapter address. IMEI. This way you are making it more unique per device.
@SuppressWarnings(&deprecation&)
@SuppressLint(&HardwareIds&)
public static String generateDeviceIdentifier(Context context) {
String pseudoId = &35& +
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.HOST.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10;
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String btId = &&;
if (bluetoothAdapter != null) {
btId = bluetoothAdapter.getAddress();
String longId = pseudoId + androidId + btId;
MessageDigest messageDigest = MessageDigest.getInstance(&MD5&);
messageDigest.update(longId.getBytes(), 0, longId.length());
// get md5 bytes
byte md5Bytes[] = messageDigest.digest();
// creating a hex string
String identifier = &&;
for (byte md5Byte : md5Bytes) {
int b = (0xFF & md5Byte);
// if it is a single digit, make sure it have 0 in front (proper padding)
if (b &= 0xF) {
identifier += &0&;
// add number to string
identifier += Integer.toHexString(b);
// hex string to uppercase
identifier = identifier.toUpperCase();
} catch (Exception e) {
Log.e(&TAG&, e.toString());
return &&;
answered Mar 8 at 14:01
1,688 1 7 28 1 & Adding the
longId and store it in a file, will make it the most unique identifier :
String uuid = UUID.randomUUID().toString(); –&
Apr 11 at 7:08 && & If all else fails, if the user does have lower than API 9 (lower than Gingerbread), has reset their phone or 'Secure.ANDROID_ID'. if returns 'null', then simply the ID returned will be solely based off their Android device information. This is where the collisions can happen. Try not to use DISPLAY, HOST or ID - these items could change. If there are collisions, there will be overlapping data. The source :
Apr 11 at 7:17
TelephonyManger.getDeviceId() Returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for CDMA phones.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
But i recommend to use:
Settings.Secure.ANDROID_ID that returns the Android ID as an unique 64-bit hex string.
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Sometimes TelephonyManger.getDeviceId() will return null, so to assure an unique id you will use this method:
public String getUniqueID(){
String myAndroidDeviceId = &&;
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (mTelephony.getDeviceId() != null){
myAndroidDeviceId = mTelephony.getDeviceId();
myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
return myAndroidDeviceId;
answered Feb 6 '15 at 15:00
66.6k 12 185 158 && & I recently discovered that a client's device of type SM-G928F / Galaxy S6 edge+ delivers only 15 instead of 16 hex digits for the Android ID. –&
Mar 13 '16 at 16:16
protected by ? Feb 5 '11 at 17:06
Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10
on this site (the ).
Would you like to answer one of these
Not the answer you're looking for? Browse other questions tagged
推荐:About This Article Many of the developers in Android require the unique Device ID of mobile handsets in special some case. for example, Device unique
相关阅读排行
相关内容推荐
请激活账号
为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。
您的注册邮箱:
如果您没有收到激活邮件,请注意检查垃圾箱。}

我要回帖

更多关于 主键的作用 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信