Intereting Posts
Пользовательский конвертер для дооснащения 2 Уменьшает ли Android скорость загрузки при выключении экрана? Лучший способ сравнить даты в Android «Поток не представляет собой хранилище ключей PKCS12» после сохранения с нового пароля на устройстве Android Как сохранить базу данных sqlite непосредственно на SD-карте Каковы различия между внутренним хранилищем, внешним хранилищем, SD-картой и съемным хранилищем? Как узнать, работает ли приложение или нет Невозможно выполнить dex: несколько файлов dex определяют Lbolts / AggregateException Перемещение папок android-sdk и sdk на другой диск Изображение обложки для Android, например, camscanner Лучшая практика приведения Материала в настройки с помощью AppCompat? Android: сохраните MediaPlayer во время обновления ориентации экрана Activity Android Retrofit2 Обновить Oauth 2 Token Множество TypeFace в одиночном TextView Как разрешить сообщение «Ожидание отладчика»?

Есть ли уникальный идентификатор устройства Android?

У Android-устройств уникальный идентификатор, и если да, то какой простой способ получить к нему доступ с помощью Java?

Solutions Collecting From Web of "Есть ли уникальный идентификатор устройства Android?"

Settings.Secure#ANDROID_ID возвращает идентификатор Android в качестве уникальной для каждого пользователя 64-разрядной шестнадцатеричной строки.

 import android.provider.Settings.Secure; private String android_id = Secure.getString(getContext().getContentResolver(), Secure.ANDROID_ID); 

ОБНОВЛЕНИЕ : по последним версиям Android многие проблемы с ANDROID_ID были решены, и я считаю, что этот подход больше не нужен. Пожалуйста, взгляните на ответ Энтони .

Полное раскрытие: мое приложение, в котором первоначально использовался подход ниже, больше не использует этот подход, и теперь мы используем подход, описанный в записи блога Android Developer, на которой ссылаются ссылки emmby (а именно, создание и сохранение UUID#randomUUID() ), ,


На этот вопрос много ответов, большинство из которых будут работать только «некоторые» времени, и, к сожалению, это недостаточно.

Основываясь на моих тестах устройств (все телефоны, по крайней мере один из которых не активирован):

  1. Все тестируемые устройства вернули значение для TelephonyManager.getDeviceId()
  2. Все GSM-устройства (все протестированные с помощью SIM-карты) вернули значение для TelephonyManager.getSimSerialNumber()
  3. Все устройства CDMA вернули значение null для getSimSerialNumber() (как и ожидалось)
  4. Все устройства с добавленной учетной записью Google вернули значение ANDROID_ID
  5. Все устройства CDMA вернули одно и то же значение (или вывод того же значения) для ANDROID_ID и TelephonyManager.getDeviceId()если во время установки была добавлена ​​учетная запись Google.
  6. У меня еще не было возможности протестировать GSM-устройства без SIM-карты, GSM-устройства без добавления аккаунта Google или любого из устройств в самолете.

Поэтому, если вам нужно что-то уникальное для самого устройства, TM.getDeviceId() должно быть достаточно. Очевидно, что некоторые пользователи более параноики, чем другие, поэтому может быть полезно хэш 1 или более из этих идентификаторов, так что строка по-прежнему практически уникальна для устройства, но явно не идентифицирует фактическое устройство пользователя. Например, используя String.hashCode() , в сочетании с 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(); 

Может привести к чему-то вроде: 00000000-54b3-e7c7-0000-000046bffd97

Он работает достаточно хорошо для меня.

Как упоминает Ричард ниже, не забывайте, что вам нужно разрешение на чтение свойств TelephonyManager , поэтому добавьте это в свой манифест:

 <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

Импортировать библиотеки

 import android.content.Context; import android.telephony.TelephonyManager; import android.view.View; 

Последнее обновление: 6/2/15


После прочтения каждого сообщения Stack Overflow о создании уникального идентификатора, блога разработчика Google и документации для Android, я чувствую, что «Pseudo ID» – лучший вариант.

Основная проблема: аппаратное обеспечение и программное обеспечение

аппаратные средства

  • Пользователь может изменить свое оборудование, планшет или планшет Android, поэтому уникальные идентификаторы, основанные на жестких, не являются хорошими идеями для пользователей TRACKING USERS
  • Для TRACKING HARDWARE это отличная идея

Программного обеспечения

  • Пользователь может стереть / изменить свой ПЗУ, если они внедрены
  • Вы можете отслеживать пользователей на разных платформах (iOS, Android, Windows и Web)
  • Лучше всего хотеть ОТПРАВИТЬ ИНДИВИДУАЛЬНОГО ПОЛЬЗОВАТЕЛЯ с их согласия, просто попросить их войти в систему (сделать это без использования OAuth)

Общая разбивка с Android

– Уникальность гарантии (включая внедренные устройства) для API => 9/10 (99,5% устройств Android)

– Дополнительные разрешения

Код Psuedo:

 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) 

Благодаря @stansult для публикации всех наших опций (в этом вопросе переполнения стека).

Список опций – причины, почему / почему бы не использовать их:

  • Электронная почта пользователя – программное обеспечение

    • Пользователь может изменить электронную почту – ВЫСОКО маловероятно
    • API 5+ <uses-permission android:name="android.permission.GET_ACCOUNTS" /> или
    • API 14+ <uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> ( Как получить основной адрес электронной почты устройства Android )
  • Пользовательский номер телефона – Программное обеспечение

    • Пользователи могут менять номера телефонов – ВЫСОКО НЕВЕРОЯТНО
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • IMEI – Оборудование (только телефоны, требуется android.permission.READ_PHONE_STATE )

    • Большинство пользователей ненавидят тот факт, что в разрешении говорится «Телефонные звонки». Некоторые пользователи дают плохие оценки, потому что они считают, что вы просто крадете личную информацию, когда все, что вы действительно хотите сделать, это отслеживать установки устройств. Очевидно, что вы собираете данные.
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • Идентификатор Android – аппаратное обеспечение (может быть нулевым, может быть изменено при сбросе по заводской настройке, может быть изменено на корневом устройстве)

    • Так как это может быть «null», мы можем проверить «null» и изменить его значение, но это означает, что он больше не будет уникальным.
    • Если у вас есть устройство с заводским сбросом, это значение может быть изменено или изменено на корневом устройстве, поэтому при записи пользовательских установок могут быть дубликаты.
  • MAC-адрес WLAN – аппаратное обеспечение (требуется android.permission.ACCESS_WIFI_STATE )

    • Это может быть вторым лучшим вариантом, но вы по-прежнему собираете и сохраняете уникальный идентификатор, который поступает непосредственно от пользователя. Очевидно, что вы собираете данные.
    • <uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
  • Bluetooth MAC-адрес – оборудование (устройства с Bluetooth, требуется android.permission.BLUETOOTH )

    • Большинство приложений на рынке не используют Bluetooth, поэтому, если ваше приложение не использует Bluetooth, и вы включаете это, пользователь может стать подозрительным.
    • <uses-permission android:name="android.permission.BLUETOOTH "/>
  • Псевдо-уникальный идентификатор – программное обеспечение (для всех Android-устройств)

    • Очень возможно, может содержать столкновения – см. Мой метод, размещенный ниже!
    • Это позволяет вам иметь «почти уникальный» идентификатор от пользователя, не принимая ничего личного. Вы можете создать свой единодушный идентификатор из информации об устройстве.

Я знаю, что нет «идеального» способа получения уникального идентификатора без использования разрешений; Однако иногда нам действительно нужно только отслеживать установку устройства. Когда дело доходит до создания уникального идентификатора, мы можем создать «псевдо уникальный идентификатор», основанный исключительно на информации, которую API Android дает нам, не используя дополнительных разрешений. Таким образом, мы можем показать уважение пользователей и попытаться предложить хороший пользовательский опыт.

С псевдо-уникальным идентификатором вы действительно сталкиваетесь только с тем, что могут быть дубликаты, основанные на том, что есть похожие устройства. Вы можете настроить комбинированный метод, чтобы сделать его более уникальным; Однако некоторым разработчикам необходимо отслеживать установки устройств, и это будет делать трюк или производительность на основе аналогичных устройств.

API => 9:

Если их Android-устройство – API 9 или более, это гарантировано будет уникальным из-за поля «Build.SERIAL».

ПОМНИТЕ , вы технически только упускаете около 0,5% пользователей , имеющих API <9 . Таким образом, вы можете сосредоточиться на остальных: это 99,5% пользователей!

API <9:

Если Android-устройство пользователя ниже API 9; Мы надеемся, что они не сделали заводской перезагрузки, и их «Secure.ANDROID_ID» будет сохранен или не «null». (См. http://developer.android.com/about/dashboards/index.html )

Если все остальное не удается:

Если все остальное не удастся, если у пользователя есть меньше, чем API 9 (ниже Gingerbread), сброс их устройства или «Secure.ANDROID_ID» возвращает «null», тогда просто возвращаемый идентификатор будет основываться исключительно на информации об устройстве Android. Здесь могут произойти столкновения.

Изменения:

  • Убрано «Android.SECURE_ID» из-за сброса фабрики может привести к изменению значения
  • Отредактирован код для изменения API
  • Изменено псевдо

Пожалуйста, ознакомьтесь с нижеприведенным методом:

 /** * 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(); } 

Новое (для приложений с рекламой и сервисами Google Play):

С консоли разработчика Google Play:

Начиная с 1 августа 2014 года в Политике программы разработчика Google Play требуется, чтобы все новые приложения и обновления приложений использовали рекламный идентификатор вместо любых других постоянных идентификаторов для любых рекламных целей. Выучить больше

Реализация :

Разрешение:

 <uses-permission android:name="android.permission.INTERNET" /> 

Код:

 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 (eg, // 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(); } 

Источник / Docs:

http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html

Важный:

Предполагается, что рекламный идентификатор полностью заменяет существующее использование других идентификаторов для целей рекламы (например, использование ANDROID_ID в Settings.Secure), когда доступны сервисы Google Play. Случаи недоступности Служб Google Play указаны с помощью исключения GooglePlayServicesNotAvailableException, полученного методом getAdvertisingIdInfo ().

Предупреждение, пользователи могут выполнить сброс:

http://en.kioskea.net/faq/34732-android-reset-your-advertising-id

Я попытался ссылаться на каждую ссылку, из которой я получил информацию. Если вы отсутствуете и должны быть включены, прокомментируйте!

Идентификатор экземпляра служб Google Player

https://developers.google.com/instance-id/

Как упоминает Дейв Вебб, в блоге разработчиков Android есть статья, которая охватывает это. Их предпочтительным решением является отслеживание приложений, а не устройств, и это будет хорошо работать для большинства случаев использования. Сообщение в блоге покажет вам необходимый код, чтобы сделать эту работу, и я рекомендую вам проверить это.

Тем не менее, в блоге идет обсуждение решений, если вам нужен идентификатор устройства, а не идентификатор установки приложения. Я поговорил с кем-то в Google, чтобы получить некоторые дополнительные разъяснения по нескольким пунктам в случае, если вам нужно это сделать. Вот что я узнал об идентификаторах устройств, которые НЕ упоминаются в вышеупомянутом сообщении в блоге:

  • ANDROID_ID является предпочтительным идентификатором устройства. ANDROID_ID отлично надежен в версиях Android <= 2.1 или> = 2.3. Только 2.2 имеет проблемы, упомянутые в сообщении.
  • Несколько устройств от нескольких производителей подвержены ошибке ANDROID_ID в 2.2.
  • Насколько мне удалось определить, все затронутые устройства имеют тот же ANDROID_ID , что и 9774d56d682e549c . Это также тот же идентификатор устройства, о котором сообщает эмулятор, кстати.
  • Google полагает, что OEM-производители исправили эту проблему для многих или большинства своих устройств, но я смог проверить, что по состоянию на начало апреля 2011 года, по крайней мере, до сих пор довольно легко найти устройства с разбитым ANDROID_ID.

Основываясь на рекомендациях Google, я внедрил класс, который будет генерировать уникальный UUID для каждого устройства, используя ANDROID_ID в качестве семени, где это необходимо, при необходимости отпадает на TelephonyManager.getDeviceId (), и если это не удается, прибегая к случайно генерируемому уникальному UUID Который сохраняется через перезагрузки приложений (но не для повторной установки приложения).

Обратите внимание, что для устройств, которые должны отступать от идентификатора устройства, уникальный идентификатор WILL сохраняется на заводских сбрасываниях. Это то, о чем нужно знать. Если вам необходимо убедиться, что сброс на завод сбросит ваш уникальный идентификатор, вам может потребоваться вернуться обратно к случайному UUID вместо идентификатора устройства.

Опять же, этот код предназначен для идентификатора устройства, а не для идентификатора установки приложения. В большинстве случаев идентификатор установки приложения, вероятно, является тем, что вы ищете. Но если вам нужен идентификатор устройства, то для вас, вероятно, будет работать следующий код.

 import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings.Secure; import android.telephony.TelephonyManager; import java.io.UnsupportedEncodingException; 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 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); } else { 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 try { if (!"9774d56d682e549c".equals(androidId)) { uuid = UUID.nameUUIDFromBytes(androidId .getBytes("utf8")); } else { 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 * purposes. */ public UUID getDeviceUuid() { return uuid; } } 

Вот код, который Reto Meier использовал в презентации ввода-вывода Google в этом году, чтобы получить уникальный идентификатор пользователя:

 private static String uniqueID = null; private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID"; public synchronized static String id(Context context) { if (uniqueID == null) { SharedPreferences sharedPrefs = context.getSharedPreferences( PREF_UNIQUE_ID, Context.MODE_PRIVATE); uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null); if (uniqueID == null) { uniqueID = UUID.randomUUID().toString(); Editor editor = sharedPrefs.edit(); editor.putString(PREF_UNIQUE_ID, uniqueID); editor.commit(); } } return uniqueID; } 

Если вы связали это с стратегией резервного копирования для отправки предпочтений в облако (также описанный в разговоре Reto, у вас должен быть идентификатор, связанный с пользователем и зависающий после того, как устройство было вытерто или даже заменено. Я планирую использовать это В аналитике в будущем (другими словами, я еще не сделал этого) :).

Также вы можете рассмотреть MAC-адрес адаптера Wi-Fi. Получено таким образом:

 WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE); return wm.getConnectionInfo().getMacAddress(); 

Требуется разрешение android.permission.ACCESS_WIFI_STATE в манифесте.

Сообщается, что он доступен, даже если Wi-Fi не подключен. Если Джо из приведенного выше ответа дает этому возможность попробовать свои многочисленные устройства, это было бы неплохо.

На некоторых устройствах он недоступен, когда Wi-Fi отключен.

ПРИМЕЧАНИЕ. Начиная с Android 6.x, он возвращает постоянный поддельный MAC-адрес: 02:00:00:00:00:00

Здесь есть довольно полезная информация.

Он охватывает пять различных типов идентификаторов:

  1. IMEI (только для Android-устройств с использованием телефона; требуется android.permission.READ_PHONE_STATE )
  2. Псевдо-уникальный идентификатор (для всех Android-устройств)
  3. Идентификатор Android (может быть нулевым, может быть изменен при перезагрузке, может быть изменен на корневом телефоне)
  4. Строка MAC-адреса WLAN (требуется android.permission.ACCESS_WIFI_STATE )
  5. BT MAC-адрес строки (устройства с Bluetooth, требуется android.permission.BLUETOOTH )

В официальном блоге разработчиков Android теперь есть полная статья именно по этому вопросу, « Определение приложений» .

В Google I / O Reto Meier был выпущен надежный ответ на вопрос о том, как подойти к этому, что должно удовлетворить большинство разработчиков, чтобы отслеживать пользователей через установки. Энтони Нолан показывает направление в своем ответе, но я думал, что напишу полный подход, чтобы другие могли легко понять, как это сделать (мне потребовалось некоторое время, чтобы разобраться в деталях).

Такой подход даст вам анонимный, безопасный идентификатор пользователя, который будет постоянным для пользователя на разных устройствах (на основе основной учетной записи Google) и между установками. Основной подход – генерировать случайный идентификатор пользователя и сохранять его в общих настройках приложений. Затем вы используете агент резервного копирования Google для хранения общих настроек, связанных с учетной записью Google в облаке.

Давайте рассмотрим полный подход. Во-первых, нам нужно создать резервную копию для наших SharedPreferences с помощью службы резервного копирования Android. Начните с регистрации своего приложения через http://developer.android.com/google/backup/signup.html .

Google предоставит вам ключ службы резервного копирования, который необходимо добавить в манифест. Вам также необходимо сообщить приложению, чтобы использовать BackupAgent следующим образом:

 <application android:label="MyApplication" android:backupAgent="MyBackupAgent"> ... <meta-data android:name="com.google.android.backup.api_key" android:value="your_backup_service_key" /> </application> 

Затем вам нужно создать резервный агент и сообщить ему использовать вспомогательный агент для sharedpreferences:

 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 @Override public void onCreate() { SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS); addHelper(PREFS_BACKUP_KEY, helper); } } 

Чтобы завершить резервное копирование, вам нужно создать экземпляр BackupManager в своей основной деятельности:

 BackupManager backupManager = new BackupManager(context); 

Наконец, создайте идентификатор пользователя, если он еще не существует, и сохраните его в SharedPreferences:

  public static String getUserID(Context context) { private static String uniqueID = null; private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID"; if (uniqueID == null) { SharedPreferences sharedPrefs = context.getSharedPreferences( MyBackupAgent.PREFS, Context.MODE_PRIVATE); uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null); if (uniqueID == null) { uniqueID = UUID.randomUUID().toString(); Editor editor = sharedPrefs.edit(); editor.putString(PREF_UNIQUE_ID, uniqueID); editor.commit(); //backup the changes BackupManager mBackupManager = new BackupManager(context); mBackupManager.dataChanged(); } } return uniqueID; } 

Этот User_ID теперь будет постоянным во всех установках, даже если пользователь перемещает устройство.

Для получения дополнительной информации об этом подходе см . Разговор Рето .

Подробные сведения о том, как реализовать агент резервного копирования, см. В разделе Резервное копирование данных . 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.

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 = null; try { Class<?> c = Class.forName("android.os.SystemProperties"); Method get = c.getMethod("get", String.class); serial = (String) get.invoke(c, "ro.serialno"); } catch (Exception ignored) { } 

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: 355715565309247 . No special permission are required, making this approach very convenient.


(Extra info: The technique given above was copied from an article on Pocket Magic .)

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); 

A Serial 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.

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.

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 Identifying App Installations .

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 = null; private static final String INSTALLATION = "INSTALLATION"; public synchronized static String id(Context context) { if (sID == null) { File installation = new File(context.getFilesDir(), INSTALLATION); try { 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(); } } 

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" /> 

Adding to what others have said, there is a new Best practices for unique identifiers guide in the official Android documentation: http://developer.android.com/training/articles/user-data-ids.html

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(); } else { deviceId = Secure.getString( getApplicationContext().getContentResolver(), Secure.ANDROID_ID); } 

But I strongly recommend a method suggested by Google, see Identifying App Installations .

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 IMEI , 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 https://github.com/ylechelle/OpenUDID ) for Android (see https://github.com/vieux/OpenUDID ). It is easy to integrate and makes use of the ANDROID_ID with fallbacks for those issues mentioned above.

How about the IMEI . That is unique for Android or other mobile devices.

My two cents – NB this is for a device (err) unique ID – not the installation one as discussed in the Android developers's blog .

Of note that the solution provided by @emmby falls back in a per application ID as the SharedPreferences are not synchronized across processes (see here and here ). 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.permission; import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.pm.PackageManager; import android.net.wifi.WifiManager; import android.provider.Settings.Secure; import android.telephony.TelephonyManager; import android.util.Log; // 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 String uuid; // 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 * bug * * @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 * thrown * @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 = uuid; if (result == null) { synchronized (DeviceIdentifier.class) { result = uuid; if (result == null) { for (IDs id : IDs.values()) { try { result = uuid = id.getId(ctx); } catch (DeviceIDNotUniqueException e) { if (!ignoreBuggyAndroidID) throw new DeviceIDException(e); } if (result != null) return result; } throw new DeviceIDException(); } } } return result; } private static enum IDs { TELEPHONY_ID { @Override 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"); return null; } assertPermission(ctx, permission.READ_PHONE_STATE); return tm.getDeviceId(); } }, ANDROID_ID { @Override 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 { @Override String getId(Context ctx) { WifiManager wm = (WifiManager) ctx .getSystemService(Context.WIFI_SERVICE); if (wm == null) { w("Wifi Manager not available"); return null; } assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess // getMacAddress() has no java doc !!! return wm.getConnectionInfo().getMacAddress(); } }, BLUETOOTH_MAC { @Override String getId(Context ctx) { BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter(); if (ba == null) { w("Bluetooth Adapter not available"); return null; } 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 = "9774d56d682e549c"; private final static String TAG = IDs.class.getSimpleName(); abstract String getId(Context ctx) throws DeviceIDException; 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 = -8083699995384519417L; 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 = -8940090896069484955L; public DeviceIDNotUniqueException() { super(ANDROID_ID_BUG_MSG); } } } 

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.

PS Their are a bunch of other Interfaces you will get from the list containing MACS But this can change between phones.

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 = null; if(Build.VERSION.SDK_INT > Build.VERSION_CODES.FROYO) serial = Build.SERIAL; if(tmDevice != null) return "01" + tmDevice; if(androidId != null) return "02" + androidId; if(serial != null) return "03" + serial; // other alternatives (ie Wi-Fi MAC, Bluetooth MAC, etc.) return null; } 

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 root 4096 2013-01-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
  • Nexus S
  • Motorola Xoom 3G
  • Toshiba AT300
  • HTC One V
  • Mini MK802
  • Samsung Galaxy S II

You can also see my blog post Leaking Android hardware serial number to unprivileged apps where I discuss what other files are available for information.

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.

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_IDSettings.Secure.ANDROID_ID
Bluetooth Address – Bluetooth adapter address

It will return something like this: 551F27C060712A72730B0A0F734064B1

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; try { 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(); return identifier; } catch (Exception e) { Log.e("TAG", e.toString()); } return ""; } 

I found a library on Github that seems to bundle a few of the approaches discussed in this thread: https://github.com/thomashaertel/android-device-identification

Haven't tried it, but maybe it helps.

Google Instance ID

Released at I/O 2015; on Android requires play services 7.5.

https://developers.google.com/instance-id/
https://developers.google.com/instance-id/guides/android-implementation

 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 accepted answer) now no longer identifies devices either. With the ARC runtime a new ANDROID_ID is generated for every installation ( details here ), 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).

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 = null; 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); 

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.

  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(); }else{ myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); } return myAndroidDeviceId; }