Is there a unique Android device ID?
Android设备是否有唯一的ID,如果有,使用Java访问它的简单方法是什么?
Settings.Secure#ANDROID_ID
将Android ID作为每个用户的64位十六进制字符串的唯一返回值。
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
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 Anthony's answer.
Full disclosure: my app used the below approach originally but no longer uses this approach, and we now use the approach outlined in the Android Developer Blog entry that emmby's answer links to (namely, generating and saving a UUID#randomUUID()
).
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):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
(as expected) ANDROID_ID
ANDROID_ID
and TelephonyManager.getDeviceId()
-- as long as a Google account has been added during setup. 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: 00000000-54b3-e7c7-0000-000046bffd97
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.Context;
import android.telephony.TelephonyManager;
import android.view.View;
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
Hardware
Software
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)
else
return unique ID of build information (may overlap data - API < 9)
Thanks to @stansult for posting all of our options (in this Stack Overflow question).
List of options - reasons why/ why not to use them:
User Email - Software
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
or <uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
(How to get the Android device's primary e-mail address) User Phone Number - Software
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
IMEI - Hardware (only phones, needs android.permission.READ_PHONE_STATE
)
<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)
WLAN MAC Address - Hardware (needs android.permission.ACCESS_WIFI_STATE
)
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
Bluetooth MAC Address - Hardware (devices with Bluetooth, needs android.permission.BLUETOOTH
)
<uses-permission android:name="android.permission.BLUETOOTH "/>
Pseudo-Unique ID - Software (for all Android devices)
I know there isn't any 'perfect' way of getting a unique ID without using permissions; 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 make it more unique; however, some developers need to track device installs and this will do the trick or performance based on similar devices.
API => 9:
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 who have API < 9. So you can focus on the rest: This is 99.5% of the users!
API < 9:
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 http://developer.android.com/about/dashboards/index.html)
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.
Changes:
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/4789483/950427
// 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 = null;
try {
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/2853253/950427
// 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" />
Code:
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;
import com.google.android.gms.common.GooglePlayServicesAvailabilityException;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import java.io.IOException;
...
// Do not call this function from the main thread. Otherwise,
// an IllegalStateException will be thrown.
public void getIdThread() {
Info adInfo = null;
try {
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:
http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html
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:
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
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
https://developers.google.com/instance-id/
链接地址: http://www.djcxy.com/p/618.html上一篇: 将具有默认值的列添加到SQL Server中的现有表
下一篇: 是否有唯一的Android设备ID?