Get Android deviceId, simple enough…?
Turns out it is not as simple as I thought to get a unique device id to identify an Android device in my app. TelephoneManager.getDeviceId() only works if the device has telephone support (of course), ANDROID_ID is apparently buggy on some pre 2.2 devices (some manufacturers always returning the same value, see http://code.google.com/p/android/issues/detail?id=10603).
This blogpost on the Android Developers blog describes the issues in more detail:
http://android-developers.blogspot.com/2011/03/identifying-app-installations.html
I ended up writing a simple factory class to handle this, falling back to a generated id that is stored in SharedPreferences if all above fails:
public class DeviceIdFactory { private static String deviceId; private static final String DEVICE_ID = "prefDeviceId"; /** * Get unique device id. * * First try Settings.Secure.ANDROID_ID. Due to a bug some manufacturers will return the same * id for Settings.Secure.ANDROID_ID. * * Fallback on TelephonyManager.getDeviceId(), which should return unique device id if telephony is * supported on device. * * Last fallback generate unique id for this installation and store as SharedPreference. * * @see http://android-developers.blogspot.com/2011/03/identifying-app-installations.html * @see http://code.google.com/p/android/issues/detail?id=10603 * @param context * @return unique id for this device (might change on factory resets, device upgrade etc) */ public static String getDeviceId(Context context) { if (deviceId == null) { synchronized (DeviceIdFactory.class) { if (deviceId == null) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); deviceId = prefs.getString(DEVICE_ID, null); if (deviceId == null) { String deviceId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID); try { if ("9774d56d682e549c".equals(deviceId)) { String tmId = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); deviceId = tmId == null ? UUID.randomUUID().toString() : UUID.nameUUIDFromBytes(tmId.getBytes("utf8")).toString(); } else { deviceId = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")).toString(); } } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } prefs.edit().putString(DEVICE_ID, deviceId).commit(); } } } } return deviceId; } }
Note: requires READ_PHONE_STATE permission