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

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


person Tyler    schedule 07.05.2010    source источник
comment
Если вы используете ANDROID_ID, обязательно прочтите этот ответ и эта ошибка < / а>.   -  person Dheeraj Vepakomma    schedule 16.01.2013


Ответы (50)


Settings.Secure#ANDROID_ID возвращает идентификатор Android в виде < href = "https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID" rel = "noreferrer"> уникальный для каждого пользователя 64-битное шестнадцатеричное нить.

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID);

Также прочтите Рекомендации для уникальных идентификаторов: https://developer.android.com/training/articles/user-data-ids

person Anthony Forloney    schedule 07.05.2010
comment
Иногда известно, что он имеет значение null, но это задокументировано, поскольку может измениться после сброса настроек. Используйте на свой страх и риск, и его можно легко изменить на рутированном телефоне. - person Seva Alekseyev; 23.06.2010
comment
Я думаю, что нам нужно быть осторожными при использовании ANDROID_ID в хэше в первом ответе, потому что он может не быть установлен при первом запуске приложения, может быть установлен позже или может даже измениться теоретически, поэтому уникальный идентификатор может измениться - person ; 05.02.2011
comment
Имейте в виду, что это решение имеет огромные ограничения: android-developers. blogspot.com/2011/03/ - person emmby; 08.04.2011
comment
этот ANDROID_ID предназначен только для вкладки Android, если вы можете работать на телефоне, тогда вы получите null, если вы запустите вкладку, тогда вы можете получить уникальный идентификатор.-Girish - person Girish Patel; 30.09.2011
comment
ANDROID_ID больше не идентифицирует устройство однозначно (начиная с версии 4.2): ​​stackoverflow.com/a/13465373/150016 - person Tom; 15.12.2012
comment
Кажется, это также может измениться, если пользователь очищает кэшированные данные Play Services. androidpolice.com/2013/11/20/ намекает на изменение основного идентификатора, по которому Google знает твое устройство. Что касается серверов, устройство было в основном сброшено до заводских настроек. что, как я предполагаю, является ANDROID_ID - я не могу воспроизвести это при тестировании - в любом случае стоит знать ... - person Dori; 06.03.2014
comment
Салам. посмотрите ответ @Joe http://stackoverflow.com/a/2853253/1676736 - person Sayed Abolfazl Fatemi; 09.07.2014
comment
Использование getString для получения идентификаторов устройств не рекомендуется. ПОЧЕМУ? - person Iman Marashi; 06.04.2017
comment
Android O изменит это android-developers.googleblog.com/2017/04/ - person EpicPandaForce; 12.04.2017
comment
Я использую Android ID в своем приложении, чтобы однозначно идентифицировать пользователей, потому что я чувствовал, что это проще, чем обычная регистрация с помощью идентификатора электронной почты, и до сих пор я не обнаружил никаких проблем с этим решением, ни один из наших подписчиков пока не жалуется, и мы знаем, что резервный вариант не будет таким разрушительным, если это произойдет снова, все зависит от типа приложения, если приложению не нужна строгая безопасность, я думаю, что идентификатор ANDROID не может быть проблемой - person Naga; 22.02.2019
comment
Android Lint говорит, что использовать getString для получения идентификаторов устройств не рекомендуется. Информация для проверки: использование этих идентификаторов устройств не рекомендуется, кроме как для предотвращения крупного мошенничества и сложных случаев использования телефонии. Для рекламных случаев используйте AdvertisingIdClient $ Info # getId, а для аналитики используйте InstanceId # getId. - person Malwinder Singh; 24.07.2019
comment
@AaronUllal, извините, немного поздно, нет, я так не думаю, в настройках About Phone есть такие вещи, как версия Android, imei и т. Д., В одном из проверенных мной телефонов Android, возможно, это не так актуально для пользователей, чем для приложений - person Naga; 03.09.2019
comment
Какая версия ответа на этот вопрос в 2020 году? Конечно, все изменилось. - person André; 24.07.2020
comment
Этот идентификатор изменяется при изменении файла хранилища ключей. Я искал что-то более уникальное. Идентификатор, который остается постоянным для одного устройства. - person Syed Arsalan Kazmi; 20.11.2020
comment
@SyedArsalanKazmi я выбрал токен fcm - person famfamfam; 05.03.2021

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

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


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

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

  1. Все протестированные устройства вернули значение TelephonyManager.getDeviceId()
  2. Все устройства GSM (все протестированы с SIM-картой) вернули значение TelephonyManager.getSimSerialNumber()
  3. Все устройства CDMA вернули нулевое значение для 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;
person Joe    schedule 17.05.2010
comment
ID на основе телефонии не будет на планшетных устройствах, не так ли? - person Seva Alekseyev; 23.06.2010
comment
Поэтому я сказал, что большинство из них не будет работать постоянно :) Я еще не нашел ответа на этот вопрос, который был бы надежным для всех устройств, всех типов устройств и всех конфигураций оборудования. Вот почему этот вопрос здесь для начала. Совершенно очевидно, что здесь нет единого решения. У отдельных производителей устройств могут быть серийные номера устройств, но мы не можем их использовать, и это не является обязательным требованием. Таким образом, у нас остается то, что нам доступно. - person Joe; 29.06.2010
comment
Вы обновите свой ответ после дополнительных тестов? Было бы довольно интересно. - person liori; 31.01.2011
comment
Пример кода отлично работает. Не забудьте добавить <uses-permission android:name="android.permission.READ_PHONE_STATE" /> в файл манифеста. При хранении в базе данных возвращаемая строка имеет длину 36 символов. - person Richard; 28.02.2011
comment
Имейте в виду, что это решение имеет огромные ограничения: android-developers. blogspot.com/2011/03/ - person emmby; 08.04.2011
comment
К вашему сведению, TelephonyManager.getDeviceId () возвращает действительный уникальный идентификатор на моем Xoom, поэтому, похоже, это работает и для планшетов. - person MusiGenesis; 21.04.2011
comment
Этот ответ устарел и не должен использоваться. Не отслеживайте устройства, отслеживайте установки! - person softarn; 17.07.2011
comment
@softarn: Я считаю, что вы имеете в виду блог разработчиков Android, на который уже есть ссылка на emmby, в котором объясняется, что вы пытаетесь сказать, так что, возможно, вам нужно было просто проголосовать за его комментарий. В любом случае, как упоминает Эмби в своем ответе, все еще есть проблемы даже с информацией в блоге. В вопросе запрашивается уникальный идентификатор DEVICE (не идентификатор установки), поэтому я не согласен с вашим утверждением. В блоге делается предположение, что то, что вы хотите не обязательно для отслеживания устройства, тогда как вопрос требует именно этого. В противном случае я согласен с блогом. - person Joe; 22.07.2011
comment
Думаю, в этом методе есть один серьезный недостаток. Это зависит от информации о SIM-карте, пользователи иногда переключаются в режим полета = SIM-карта не подключена. В этом сценарии вам понадобится резервный механизм, возможно, для использования Android ID. - person Daniel Novak; 04.08.2011
comment
@ Даниэль Новак: справедливо. В моем случае это не актуально, потому что идентификатор используется в API-связи, поэтому режим полета = нет приложения :) Мы также разработали его таким образом, чтобы, например, если пользователь меняет SIM-карты, мы намеренно хотели получить идентификатор устройства. Быть другим. Очевидно, что это относится не ко всем, поэтому спасибо, что указали на это. - person Joe; 22.08.2011
comment
Я немного удивлен, что никто еще не поднял этот вопрос, но пример кода может быть действительно неудачным в некоторых обстоятельствах - он вернет другой идентификатор в зависимости от того, находится ли телефон, например, в режиме полета или нет, поскольку simSerialNumber будет нулевым, если сеть GSM устройства отключена. Если у вас есть приложение, которое использует уникальный идентификатор, но ему нужен только Интернет, а не обязательно сеть, может быть лучше убедиться, что код всегда возвращает один и тот же идентификатор независимо от текущего состояния сети телефона. - person Mathias; 20.12.2011
comment
Я использую этот код 6 месяцев. Он не создает уникальный идентификатор. Я не рекомендую всем использовать этот код. В настоящее время я использую код из этого сообщения: stackoverflow.com/a/17625641/365229 - person Behrouz.M; 18.06.2015
comment
Я настоятельно рекомендую вам не использовать этот код. В нем есть несколько критических ошибок: во-первых, нет гарантии, что и телефония, и Android ID существуют, и если они оба не существуют, ваши устройства будут сопоставлены только в соответствии с их моделью. Во-вторых, что более важно, когда вы используете хэш-код Android ID, вы превращаете 64-битное строковое представление числа в 32-битное число, и, таким образом, вы теряете большую часть уникальности. - person lavuy; 30.07.2015
comment
Идентификатор IMEI больше не может работать на Android 10 и выше. - person abss; 13.07.2021

# Последнее обновление: 02.06.15


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

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

Аппаратное обеспечение

  • Пользователи могут менять свое оборудование, планшет Android или телефон, поэтому уникальные идентификаторы, основанные на оборудовании, не подходят для ОТСЛЕЖИВАНИЯ ПОЛЬЗОВАТЕЛЕЙ.
  • Для ОТСЛЕЖИВАНИЯ ОБОРУДОВАНИЯ это отличная идея.

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

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

# Общая поломка с Android

### - Гарантия уникальности (включая рутированные устройства) для API ›= 9/10 (99,5% устройств Android) ### - Без дополнительных разрешений

Псевдокод:

if API >= 9/10: (99.5% of devices)

return unique ID containing serial id (rooted devices may be different)

else

return the 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" /> (Как получить основной адрес электронной почты)

  • Номер телефона пользователя - программное обеспечение

  • Пользователи могут менять номера телефонов - Маловероятно

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

  • MAC-адрес Bluetooth - оборудование (для устройств с Bluetooth требуется android.permission.BLUETOOTH)

  • Большинство приложений на рынке не используют Bluetooth, поэтому, если ваше приложение не использует Bluetooth и вы его включаете, пользователь может заподозрить подозрение.

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

  • Псевдоуникальный идентификатор - программное обеспечение (для всех устройств Android)

  • Очень возможно, могут содержать коллизии - см. Мой метод, опубликованный ниже!

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


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

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

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

Источник / Документы:

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/

person Jared Burrows    schedule 12.07.2013
comment
Я использовал ваш метод в своем приложении для отправки комментариев. У меня плохие новости. к сожалению, PsuedoID не является полностью уникальным. мой сервер записал более 100 для 5 ID и более 30 для почти 30 ID. наиболее часто повторяющимися идентификаторами являются «ffffffff-fc8f-6093-ffff-ffffd8» (159 записей) и «ffffffff-fe99-b334-ffff-ffffef» (154 раза). также судя по времени и комментариям, очевидно, что есть разные народы. общее количество записей до сих пор составляет 10 000. пожалуйста, дайте мне знать, почему это произошло. танки. - person hojjat reyhane; 17.03.2015
comment
Я написал это 1,5+ года назад. Я не уверен, почему это не уникально для вас. Вы можете попробовать рекламный идентификатор. Если нет, вы можете предложить собственное решение. - person Jared Burrows; 17.03.2015
comment
вроде .. Буду очень признателен, если вы ответите на вопрос и поделитесь своим мнением по этому поводу - person Durai Amuthan.H; 29.04.2015
comment
@ user1587329 Спасибо. Я стараюсь держать это в курсе для всех. Это сложный вопрос, когда речь идет об аппаратном обеспечении, программном обеспечении и кросс-платформе. - person Jared Burrows; 06.05.2015

Как упоминает Дэйв Уэбб, в блоге разработчиков 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. который сохраняется при перезапуске приложения (но не при повторной установке приложения).

Обратите внимание, что для устройств, которые должны использовать резервный идентификатор устройства, уникальный идентификатор БУДЕТ сохраняться при заводских сбросах. Об этом следует помнить. Если вам нужно убедиться, что при сбросе к заводским настройкам ваш уникальный идентификатор будет сброшен, вы можете рассмотреть возможность возврата непосредственно к случайному 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;
    }
}
person emmby    schedule 11.04.2011
comment
Разве вы не должны хэшировать различные идентификаторы, чтобы они все были одного размера? Кроме того, вы должны хешировать идентификатор устройства, чтобы случайно не раскрыть личную информацию. - person Steve Pomeroy; 12.04.2011
comment
Кроме того, устройство, конфигурация которого вызывает использование идентификатора устройства, привяжет идентификатор к устройству, не обязательно к пользователю. Этот идентификатор переживет сброс настроек до заводских, что потенциально может быть плохим. Может быть, идентификатор устройства может быть хеширован с помощью чего-то, что сообщает время последнего сброса настроек? - person Steve Pomeroy; 12.04.2011
comment
Хорошие замечания, Стив. Я обновил код, чтобы всегда возвращать UUID. Это гарантирует, что а) сгенерированные идентификаторы всегда имеют одинаковый размер и б) идентификаторы Android и устройства хешируются перед возвратом, чтобы избежать случайного раскрытия личной информации. Я также обновил описание, чтобы отметить, что идентификатор устройства будет сохраняться при заводских сбросах и что это может быть нежелательно для некоторых пользователей. - person emmby; 12.04.2011
comment
Я считаю, что вы ошибаетесь; предпочтительным решением является отслеживание установок, а не идентификаторов устройств. Ваш код значительно длиннее и сложнее, чем в сообщении в блоге, и для меня не очевидно, что он добавляет какую-либо ценность. - person Tim Bray; 12.04.2011
comment
Хороший момент, я обновил комментарий, чтобы настоятельно рекомендовать пользователям использовать идентификаторы установки приложений, а не идентификаторы устройств. Однако я думаю, что это решение по-прежнему полезно для людей, которым нужно устройство, а не идентификатор установки. - person emmby; 12.04.2011
comment
ANDROID_ID может измениться при сбросе настроек, поэтому он также не может идентифицировать устройства - person Samuel; 19.05.2011
comment
Как я отмечаю в вашем ответе здесь, есть нет гарантии, что вы получите один и тот же сгенерированный UUID для всех процессов - копия SharedPrefs является локальной! - person Mr_and_Mrs_D; 18.09.2013

Вот код, который Рето Мейер использовал в презентации Google I / O в этом году, чтобы получить уникальный идентификатор для Пользователь:

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 talk, у вас должен быть идентификатор, который привязан к пользователю и остается после очистки устройства или даже замены. Я планирую использовать его в аналитике. в будущем (другими словами, я еще не сделал этого :).

person Anthony Nolan    schedule 28.10.2011
comment
Отличный вариант, если вам не нужен уникальный идентификатор для сохранения после удаления и повторной установки (например, рекламное мероприятие / игра, в которой у вас есть три шанса на победу, точка). - person Kyle Clegg; 16.05.2012
comment
Презентация Мейера основана на использовании Android Backup Manager, который, в свою очередь, зависит от выбора пользователем этой функции. Это нормально для пользовательских предпочтений приложения (использование Мейера), потому что, если пользователь не выбрал этот вариант, он просто не получит их резервные копии. Однако исходный вопрос касается создания уникального идентификатора для устройства, и этот идентификатор создается для каждого приложения, а не для каждой установки, не говоря уже о каждом устройстве, и поскольку он зависит от выбора пользователем вариант резервного копирования, его использование, выходящее за рамки предпочтений пользователя (например, для ограниченного по времени пробного периода), ограничено. - person Carl; 22.12.2012
comment
Это не сработает при удалении или очистке данных. - person John Shelley; 02.09.2014
comment
очень плохое решение - person famfamfam; 23.02.2021
comment
Я думаю, что это хорошее решение, на устройстве и на сервере есть уникальный идентификатор на случай удаления. Вы можете убедиться, что сохранили его по электронной почте клиента, чтобы он прилипал ;-p - person vin shaba; 25.04.2021

Также вы можете рассмотреть 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

person Seva Alekseyev    schedule 23.06.2010
comment
Это требовало android.permission.ACCESS_WIFI_STATE - person ohhorob; 01.11.2010
comment
как насчет устройств без Wi-Fi? - person Axarydax; 22.12.2010
comment
Я знаю, что это старый вопрос, но это отличная идея. Я использовал идентификатор BT Mac в своем приложении, но только потому, что для его работы требуется BT. Покажите мне Android-устройство, которое стоит разработать, но без Wi-Fi. - person Jack; 30.08.2011
comment
Я думаю, вы обнаружите, что он недоступен при отключенном Wi-Fi практически на всех устройствах Android. При отключении Wi-Fi устройство удаляется на уровне ядра. - person chrisdowney; 22.05.2012
comment
@Sanandrea - давайте посмотрим правде в глаза, на рутированном устройстве ВСЕ может быть подделано. - person ocodo; 04.09.2013
comment
Как сказано в блоге Google, MAC - не лучший вариант. Можно получить Mac-адрес с оборудования Wi-Fi или Bluetooth устройства. Мы не рекомендуем использовать это как уникальный идентификатор. Начнем с того, что не на всех устройствах есть Wi-Fi. Кроме того, если Wi-Fi не включен, оборудование может не сообщать Mac-адрес. android-developers.blogspot.com.es/2011/ 03 / - person jiahao; 01.06.2014
comment
Доступ к MAC-адресу Wi-Fi заблокирован на Android M: stackoverflow.com/questions/31329733/ - person breez; 22.12.2015
comment
В частности, локальные MAC-адреса WiFi и Bluetooth больше не доступны. Метод getMacAddress () объекта aWifiInfo и метод BluetoothAdapter.getDefaultAdapter (). GetAddress () с этого момента будут возвращать 02: 00: 00: 00: 00: 00 - person sarika kate; 30.03.2016
comment
некоторые устройства могут не иметь Wi-Fi (лично испытал) - person Alberto M; 31.05.2016
comment
Начиная с Android 6.x он возвращает последовательный поддельный MAC-адрес: 02:00:00:00:00:00 - person Behrouz.M; 10.07.2016
comment
android 10+ рандомизирует MAC-адрес, поэтому я не рекомендую это решение - person Hari Shankar S; 09.11.2020

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

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

  1. IMEI (только для устройств Android с телефоном; требуется android.permission.READ_PHONE_STATE)
  2. Псевдоуникальный идентификатор (для всех устройств Android)
  3. Android ID (может быть пустым, может измениться после сброса настроек, может быть изменен на телефоне с рутированным доступом)
  4. Строка MAC-адреса WLAN (требуется android.permission.ACCESS_WIFI_STATE)
  5. Строка MAC-адреса BT (для устройств с Bluetooth требуется android.permission.BLUETOOTH)
person stansult    schedule 08.02.2012
comment
Упущен важный момент (здесь и в статье): вы не можете получить WLAN или BT MAC, если они не включены! В противном случае я думаю, что MAC-адрес WLAN был бы идеальным идентификатором. У вас нет гарантии, что пользователь когда-либо включит свой Wi-Fi, и я действительно не думаю, что «уместно» включать его самостоятельно. - person Tom; 08.10.2012
comment
@Tom ты ошибаешься. Вы все еще можете читать WLAN или BT MAC, даже когда они выключены. Однако нет гарантии, что в устройстве доступны модули WLAN или BT. - person Marqs; 04.08.2014
comment
В частности, локальные MAC-адреса WiFi и Bluetooth больше не доступны. Метод getMacAddress () объекта aWifiInfo и метод BluetoothAdapter.getDefaultAdapter (). GetAddress () с этого момента будут возвращать 02: 00: 00: 00: 00: 00 - person sarika kate; 30.03.2016
comment
@sarikakate Это правда только в 6.0 Marshmallow и выше ... Он все еще работает, как ожидалось, в версиях ниже 6.0 Marshmallow. - person Smeet; 13.04.2016

Это простой вопрос, на который нет простого ответа.

Более того, все существующие ответы здесь устарели или ненадежны.

Итак, если вы ищете решение в 2020 году.

Вот несколько вещей, о которых следует помнить:

Все аппаратные идентификаторы (SSAID, IMEI, MAC и т. Д.) Ненадежны для устройств, не принадлежащих Google (все, кроме пикселей и нексусов), которые составляют более 50% активных устройств во всем мире. Поэтому в официальном передовых методах работы с идентификаторами Android четко указано:

Избегайте использования аппаратных идентификаторов, таких как SSAID (Android ID), IMEI, MAC-адрес и т. д.

Это делает большинство приведенных выше ответов недействительными. Также из-за различных обновлений безопасности Android некоторые из них требуют более новых и более строгих разрешений времени выполнения, которые могут быть просто отклонены пользователем.

В качестве примера CVE-2018-9489, который влияет на все упомянутые выше методы на основе WIFI.

Это делает эти идентификаторы не только ненадежными, но и во многих случаях недоступными.

Проще говоря: не используйте эти методы.

Многие другие ответы здесь предлагают использовать AdvertisingIdClient, который также несовместим, так как его дизайн должен использоваться только для профилирования рекламы. Это также указано в официальном справочнике.

Используйте рекламный идентификатор только для профилей пользователей или вариантов использования рекламы

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

Так что тоже не используйте его.

Поскольку у вас не может быть желаемого статического глобально уникального и надежного идентификатора устройства. Официальный справочник Android предлагает:

По возможности используйте FirebaseInstanceId или GUID, хранящийся в частном порядке для всех других случаев использования, кроме предотвращения мошенничества с платежами и телефонной связи.

Это уникально для установки приложения на устройство, поэтому, когда пользователь удаляет приложение, оно стирается, поэтому оно не на 100% надежно, но это еще одна лучшая вещь.

Чтобы использовать FirebaseInstanceId, добавьте последнюю зависимость обмена сообщениями firebase в свой gradle

implementation 'com.google.firebase:firebase-messaging:20.2.4'

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

String reliableIdentifier = FirebaseInstanceId.getInstance().getId();

Если вам нужно сохранить идентификацию устройства на удаленном сервере, сохраняйте его не как есть (обычный текст), а как хеш с солью.

Сегодня это не только лучшая практика, вы фактически должны делать это по закону в соответствии с GDPR - идентификаторы и аналогичные правила.

person Nikita Kurtin    schedule 28.11.2019
comment
На данный момент это лучший ответ, а первое предложение - лучшее резюме: это простой вопрос без простого ответа - просто полюбите его. - person b2mob; 22.01.2020
comment
@ M.UsmanKhan, ответ пишется сразу после этого: Сегодня это не только лучшая практика, вы фактически должны делать это по закону в соответствии с GDPR - идентификаторами и аналогичными правилами. - person Nikita Kurtin; 08.03.2020
comment
Не могли бы вы указать, в каком разделе опубликованной вами ссылки GDPR упоминается требование хеширования идентификаторов? - person David Schneider; 21.07.2020
comment
@DavidSchneider веб-контент является динамичным по своей природе, и GDPR является лишь одним из примеров, обратите внимание, что я написал GDPR и аналогичные правила, так как существует множество местных и глобальных правил, которые влияют на ваши продукт / система / поле. В любом случае разделы GDPR, которые вы ищете: Идентификация, Онлайн-идентификаторы и Принципы защиты данных - person Nikita Kurtin; 21.07.2020
comment
proandroiddev.com/ - person william gouvea; 03.01.2021
comment
Уникальный идентификатор firebase изменится, если приложение будет переустановлено - person famfamfam; 23.02.2021
comment
@famfamfam, именно поэтому я написал, что: Он уникален для установки приложения на устройстве, поэтому, когда пользователь удаляет приложение, оно стирается, поэтому оно не на 100% надежно, но это следующая лучшая вещь . - person Nikita Kurtin; 25.02.2021
comment
спасибо, мне интересно, почему Android не может сделать ANDROID_ID для uuid устройства, чтобы усложнить код разработчика Android - person famfamfam; 25.02.2021
comment
@famfamfam Скорее всего, это из-за открытой природы Android и UUID.randomUUID() псевдослучайной платформы Java, зависящей от времени. - person Nikita Kurtin; 25.02.2021
comment
Подождите, разве не так много обстоятельств, которые заставили бы это изменить с одного значения на другое? - person Michael Paccione; 03.07.2021

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

person BoD    schedule 06.04.2011
comment
Ключевым моментом этого аргумента является то, что если вы пытаетесь получить уникальный идентификатор оборудования, вы, вероятно, делаете ошибку. - person Tim Bray; 12.04.2011
comment
И если вы разрешаете сброс блокировки устройства с помощью заводских настроек, ваша пробная модель практически мертва. - person Seva Alekseyev; 04.05.2011
comment
И сообщение в блоге уже ссылается на этот сайт: developer.android.com/training/ статьи / идентификаторы-данных-пользователей - person Bruno Bieri; 16.09.2020

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

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

Давайте рассмотрим полный подход. Во-первых, нам нужно создать резервную копию наших SharedPreferences с помощью Android Backup Service. Начните с регистрации своего приложения через 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>

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

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 в вашем основном Activity:

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 теперь будет постоянным для всех установок, даже если пользователь перемещает устройство.

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

А для получения полной информации о том, как реализовать агент резервного копирования, см. Резервное копирование данных . Я особенно рекомендую раздел внизу, посвященный тестированию, поскольку резервное копирование не происходит мгновенно, и поэтому для тестирования вам нужно принудительно выполнить резервное копирование.

person TechnoTony    schedule 22.12.2012
comment
Разве это не приводит к появлению нескольких устройств с одним и тем же идентификатором, когда у пользователя несколько устройств? Например, планшет и телефон. - person Tosa; 13.03.2013

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

Псевдоуникальный идентификатор, который работает на всех устройствах Android. На некоторых устройствах нет телефона (например, планшеты), или по какой-то причине вы не хотите включать разрешение READ_PHONE_STATE. Вы по-прежнему можете читать такие детали, как версия ПЗУ, название производителя, тип процессора и другие сведения об оборудовании, которые хорошо подойдут, если вы хотите использовать идентификатор для проверки серийного ключа или других общих целей. Вычисленный таким образом идентификатор не будет уникальным: можно найти два устройства с одинаковым идентификатором (на основе одного и того же оборудования и образа ПЗУ), но изменения в реальных приложениях незначительны. Для этого вы можете использовать класс Build:

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

Большинство членов Build являются строками, и мы здесь берем их длину и преобразуем ее по модулю в цифру. У нас есть 13 таких цифр, и мы добавляем еще две впереди (35), чтобы иметь идентификатор того же размера, что и IMEI (15 цифр). Здесь есть и другие возможности, просто взгляните на эти строки. Возвращает что-то вроде 355715565309247. Специального разрешения не требуется, что делает такой подход очень удобным.


(Дополнительная информация: описанная выше техника была скопирована из статьи на Pocket Magic.)

person Lenn Dolling    schedule 24.03.2011
comment
Интересное решение. Похоже, что это ситуация, когда вам действительно нужно просто хешировать все эти объединенные данные вместо того, чтобы пытаться придумать свою собственную хеш-функцию. Есть много случаев, когда вы можете столкнуться с коллизиями, даже если есть существенные данные, которые различаются для каждого значения. Моя рекомендация: используйте хеш-функцию, а затем преобразуйте двоичные результаты в десятичные и при необходимости усеките их. Чтобы сделать это правильно, вам действительно следует использовать UUID или полную хеш-строку. - person Steve Pomeroy; 12.04.2011
comment
Я обнаружил, что Build.CPU_ABI и Build.MANUFACTURER присутствуют не во всех версиях .. Я получал серьезные ошибки сборки при работе с ‹2.2 :) - person Lenn Dolling; 15.05.2011
comment
Вы должны отдать должное своим источникам ... Это было поднято прямо из следующей статьи: pocketmagic. net /? p = 1662 - person Steve Haley; 16.05.2011
comment
Этот идентификатор открыт для коллизий, как будто вы не знаете какие. Практически гарантированно будет то же самое на идентичных устройствах от одного и того же оператора. - person Seva Alekseyev; 27.05.2011
comment
Это также может измениться при обновлении устройства. - person David Given; 25.01.2012
comment
Не думаю, что использовать это решение - хорошая идея. Насколько я понимаю, все поля сборки будут одинаковыми для всех телефонов, производимых вместе. - person Victor Ronin; 26.07.2012
comment
Согласно комментарию Дэвида Гивена, это кажется серьезной проблемой. Следует провести тщательную инвентаризацию атрибутов сборки, чтобы определить, какие из них вряд ли изменятся в результате беспроводного обновления. Например, Build.DISPLAY, приведенный выше, согласно Javadoc, представляет собой строку идентификатора сборки, предназначенную для отображения пользователю, так что вряд ли она изменится при обновлении? Я все еще думаю, что этот подход может добавить полезные отличительные атрибуты в сочетании с другой информацией с устройства, но только если такие атрибуты, изменяемые OTA, могут быть тщательно отбракованы. - person Carl; 23.12.2012
comment
Аналогичным образом Build.HOST определяется как строка, которая однозначно идентифицирует хост, на котором была ВСТРОЕНА сборка, в удобочитаемом формате. Вполне возможно, что для создания сборки для обновления OTA можно использовать разные машины BUILD. - person Carl; 23.12.2012
comment
Очень и очень плохое решение. Проверено на двух Nexus 5 ... Возвращает одинаковые числа. - person Sinan Dizdarević; 04.03.2015

Следующий код возвращает серийный номер устройства с помощью скрытого Android API. Но этот код не работает на Samsung Galaxy Tab, потому что «ro.serialno» не установлен на этом устройстве.

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

}
person Roman SL    schedule 25.01.2011

Используя приведенный ниже код, вы можете получить уникальный идентификатор устройства на ОС Android в виде строки.

deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 
person Mohit Kanada    schedule 17.05.2011

Поле Serial было добавлено к классу Build на уровне API 9. (Android 2.3 - Gingerbread). В документации указано, что он представляет собой серийный номер оборудования. Таким образом, он должен быть уникальным, если он существует на устройстве.

Я не знаю, поддерживается ли он на самом деле (= не null) всеми устройствами с уровнем API> = 9.

person rony l    schedule 06.03.2011
comment
К сожалению, неизвестно. - person m0skit0; 15.04.2013

Я добавлю одну вещь - у меня одна из тех уникальных ситуаций.

С использованием:

deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);

Оказывается, даже несмотря на то, что мой Viewsonic G Tablet сообщает DeviceID, который не равен NULL, каждый G Tablet сообщает одно и то же число.

Делает интересной игру в «Pocket Empires», которая дает вам мгновенный доступ к чьей-либо учетной записи на основе «уникального» DeviceID.

В моем устройстве нет сотового радио.

person Tony Maro    schedule 21.03.2011
comment
@ Treewallie это работает? Можно ли получить одинаковый идентификатор устройства из разных приложений? - person Arnold Brown; 04.02.2020

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

Кажется, лучший способ - создать его самостоятельно при установке и впоследствии прочитать его при повторном запуске приложения.

Я лично считаю это приемлемым, но не идеальным. Ни один идентификатор, предоставляемый Android, не работает во всех случаях, поскольку большинство из них зависит от состояния радиосвязи телефона (включение / выключение Wi-Fi, включение / выключение сотовой связи, включение / выключение Bluetooth). Остальные, такие как Settings.Secure.ANDROID_ID, должны быть реализованы производителем, и их уникальность не гарантируется.

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

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();
    }
}
person Kevin Parker    schedule 02.08.2011
comment
Если вы хотите отслеживать установки приложений, это идеально. Однако устройства слежения намного сложнее, и, похоже, не существует полностью герметичного решения. - person Luca Spiller; 03.10.2011
comment
А как насчет рутированных устройств? Они могут легко изменить этот установочный идентификатор, не так ли? - person tasomaniac; 10.05.2012
comment
Абсолютно. Root может изменить ID установки. Вы можете проверить наличие root с помощью этого блока кода: stackoverflow.com/questions/1101380/ - person Kevin Parker; 18.05.2012
comment
если мы сбросим заводские настройки, файл будет удален? - person Jamshid; 08.01.2015
comment
Если вы сбросите настройки и удалите или отформатируете раздел / data, UUID будет другим. - person Kevin Parker; 12.01.2015

Добавьте код ниже в файл класса:

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

Добавьте в AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
person Android    schedule 27.02.2013

Существует множество различных подходов к решению этих ANDROID_ID проблем (иногда null или устройства определенной модели всегда возвращают один и тот же идентификатор) с плюсами и минусами:

  • Реализация алгоритма генерации пользовательского идентификатора (на основе свойств устройства, которые должны быть статическими и не изменятся -> кто знает)
  • Злоупотребление другими идентификаторами, такими как IMEI, серийный номер, MAC-адрес Wi-Fi / Bluetooth (они выиграли ' существуют на всех устройствах или необходимы дополнительные разрешения)

Я предпочитаю использовать существующую реализацию OpenUDID (см. https://github.com/ylechelle/OpenUDID) для Android (см. https://github.com/vieux/OpenUDID). Его легко интегрировать, и он использует ANDROID_ID с запасными вариантами для решения упомянутых выше проблем.

person Andreas Klöber    schedule 18.11.2012

Уникальный идентификатор устройства Android OS в виде строки с использованием TelephonyManager и ANDROID_ID получается следующим образом:

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

Но я настоятельно рекомендую метод, предложенный Google, см. Идентификация Установки приложений.

person Jorgesys    schedule 13.01.2014

Здесь более 30 ответов, и некоторые из них одинаковы, а некоторые уникальны. Этот ответ основан на немногих из этих ответов. Один из них - ответ @Lenn Dolling.

Он объединяет 3 идентификатора и создает 32-значную шестнадцатеричную строку. У меня это сработало очень хорошо.

3 идентификатора:
Псевдо-идентификатор - создается на основе технических характеристик физического устройства
ANDROID_ID - Settings.Secure.ANDROID_ID
Адрес Bluetooth - адрес адаптера Bluetooth

Он вернет примерно следующее: 551F27C060712A72730B0A0F734064B1.

Примечание. Вы всегда можете добавить дополнительные идентификаторы в строку longId. Например, серийный номер. адрес адаптера Wi-Fi. IMEI. Таким образом, вы делаете его более уникальным для каждого устройства.

@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 "";
}
person ᴛʜᴇᴘᴀᴛᴇʟ    schedule 08.03.2017
comment
Добавление UUID в longId и сохранение его в файле сделает его наиболее уникальным идентификатором. : String uuid = UUID.randomUUID().toString(); - person Mousa Alfhaily; 11.04.2017
comment
Если все остальное не помогает, если у пользователя ниже API 9 (ниже, чем Gingerbread), он сбросил свой телефон или «Secure.ANDROID_ID». если возвращается значение «null», то просто возвращаемый идентификатор будет основан исключительно на информации об их устройстве Android. Вот где могут произойти столкновения. Старайтесь не использовать DISPLAY, HOST или ID - эти элементы могут измениться. Если есть коллизии, данные будут перекрываться. Источник: gist.github.com/pedja1/fe69e8a80ed505500caa. - person Mousa Alfhaily; 11.04.2017
comment
@Ninja Поскольку MAC-адрес BLE уникален, да, сгенерированный идентификатор всегда будет уникальным. Однако, если вы действительно хотите быть уверенным, я бы предложил добавить UUID в longId. Измените эту строку следующим образом: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString(); Это гарантирует, что сгенерированный идентификатор будет уникальным. - person ᴛʜᴇᴘᴀᴛᴇʟ; 03.04.2019

Как насчет IMEI. Это уникально для Android или других мобильных устройств.

person Elzo Valugi    schedule 14.07.2011
comment
Не для моих планшетов, у которых нет IMEI, поскольку они не подключаются к моему оператору мобильной связи. - person Brill Pappin; 05.01.2012
comment
Не говоря уже об устройствах CDMA, у которых есть ESN вместо IMEI. - person David Given; 25.01.2012
comment
Он только то, что это телефон :) Планшет не может. - person Brill Pappin; 26.01.2012
comment
@ElzoValugi Это уже сейчас, и еще не все планшеты имеют SIM-карты. - person MLQ; 25.09.2012

Вот как я генерирую уникальный идентификатор:

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 (i.e. Wi-Fi MAC, Bluetooth MAC, etc.)

    return null;
}
person Eng.Fouad    schedule 27.05.2013
comment
если мы используем ReadPhoneState в версии 6.0, запрашивая разрешение на выполнение - person Harsha; 17.11.2016

Мои два цента - NB, это для уникального идентификатора устройства (err), а не для установочного, как описано в Блог разработчиков Android.

Следует отметить, что решение, предоставляемое @emmby, возвращается к индивидуальному идентификатору приложения, поскольку SharedPreferences не синхронизируются между процессами (см. здесь и здесь). Так что я этого вообще избегал.

Вместо этого я инкапсулировал различные стратегии получения идентификатора (устройства) в перечисление - изменение порядка констант перечисления влияет на приоритет различных способов получения идентификатора. Возвращается первый ненулевой идентификатор или генерируется исключение (в соответствии с хорошими практиками Java, не придающими значения null). Так, например, у меня сначала есть ТЕЛЕФОНИЯ, но хорошим выбором по умолчанию будет ANDROID_ID бета:

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);
        }
    }
}
person Mr_and_Mrs_D    schedule 18.09.2013

Другой способ - использовать /sys/class/android_usb/android0/iSerial в приложении без каких-либо разрешений.

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

Чтобы сделать это в Java, нужно просто использовать FileInputStream, чтобы открыть файл iSerial и прочитать символы. Просто убедитесь, что вы заключили его в обработчик исключений, потому что не на всех устройствах есть этот файл.

Известно, что этот файл доступен для чтения всем, по крайней мере, на следующих устройствах:

  • Galaxy Nexus
  • Nexus S
  • Motorola Xoom 3G
  • Toshiba AT300
  • HTC One V
  • Мини MK802
  • Samsung Galaxy S II

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

person insitusec    schedule 31.01.2013
comment
Я только что прочитал твое сообщение в блоге. Я считаю, что это не уникально: Build.SERIAL также доступен без каких-либо разрешений и (теоретически) является уникальным серийным номером оборудования. - person Tom; 01.05.2013
comment
Ты прав. Это всего лишь еще один способ отслеживания вашего устройства, и, как вы сказали, оба эти способа не требуют разрешений приложений. - person insitusec; 14.03.2014

TelephonyManger.getDeviceId () Возвращает уникальный идентификатор устройства, например IMEI для GSM и MEID или ESN для телефонов CDMA.

final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            
String myAndroidDeviceId = mTelephony.getDeviceId(); 

Но рекомендую использовать:

Settings.Secure.ANDROID_ID, который возвращает идентификатор Android в виде уникальной 64-битной шестнадцатеричной строки.

    String   myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 

Иногда TelephonyManger.getDeviceId () возвращает null, поэтому для обеспечения уникального идентификатора вы будете использовать этот метод:

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;
}
person Jorgesys    schedule 06.02.2015
comment
Недавно я обнаружил, что клиентское устройство типа SM-G928F / Galaxy S6 edge + предоставляет только 15 шестнадцатеричных цифр вместо 16 для идентификатора Android. - person Holger Jakobs; 13.03.2016

Идентификатор экземпляра Google

Выпущено на I / O 2015; на Android требуются игровые сервисы 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

Похоже, что Google намеревается использовать этот идентификатор для идентификации установок в Android, Chrome и iOS.

Он идентифицирует установку, а не устройство, но, опять же, ANDROID_ID (который является принятым ответом) теперь также больше не идентифицирует устройства. В среде выполнения ARC для каждой установки создается новый ANDROID_ID (подробности здесь), как и этот новый идентификатор экземпляра. Кроме того, я думаю, что идентификация установок (а не устройств) - это то, что на самом деле ищет большинство из нас.

Преимущества идентификатора экземпляра

Мне кажется, что Google намеревается использовать его для этой цели (для идентификации ваших установок), он является кроссплатформенным и может использоваться для ряда других целей (см. Ссылки выше).

Если вы используете GCM, вам в конечном итоге потребуется использовать этот идентификатор экземпляра, потому что он вам понадобится для получения токена GCM (который заменяет старый регистрационный идентификатор GCM).

Недостатки / проблемы

В текущей реализации (GPS 7.5) идентификатор экземпляра извлекается с сервера, когда ваше приложение запрашивает его. Это означает, что приведенный выше вызов является блокирующим - в моем ненаучном тестировании он занимает 1-3 секунды, если устройство подключено к сети, и 0,5 - 1,0 секунды, если устройство отключено (предположительно, это то время, которое он ждет, прежде чем сдаться и сгенерировать случайный идентификатор). Это было протестировано в Северной Америке на Nexus 5 с Android 5.1.1 и GPS 7.5.

Если вы используете идентификатор для целей, которые они намереваются - например. аутентификация приложения, идентификация приложения, GCM - я думаю, что эти 1-3 секунды могут доставить неудобства (конечно, в зависимости от вашего приложения).

person Tom    schedule 19.06.2015
comment
Еще одним существенным недостатком instanceID является то, что для вас будет сгенерирован новый instanceID, если пользователь очистит данные приложения. - person idanakav; 08.07.2015
comment
Интересно, но я не думаю, что это действительно меняет потенциальные варианты использования: идентификатор экземпляра, например android_id, не подходит для идентификации устройства. Таким образом, ваш сервер будет видеть данные, очищаемые пользователем, как будто пользователь удаляет и повторно устанавливает ваше приложение, что не является необоснованным. - person Tom; 08.07.2015

Для аппаратного распознавания конкретного устройства Android вы можете проверить MAC-адреса.

вы можете сделать это так:

в AndroidManifest.xml

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

теперь в вашем коде:

List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());

for (NetworkInterface interface : interfacesList) {
   // This will give you the interface MAC ADDRESS
   interface.getHardwareAddress();
}

В каждом устройстве Android есть по крайней мере интерфейс "wlan0", который является чипом WI-FI. Этот код работает даже когда WI-FI не включен.

P.S. Это множество других интерфейсов, которые вы получите из списка, содержащего MACS, но это может меняться между телефонами.

person Ilan.b    schedule 01.09.2015

Я использую следующий код для получения IMEI или использую Secure.ANDROID_ID в качестве альтернативы, когда у устройства нет возможностей телефона:

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);
person Asaf Pinhassi    schedule 15.04.2013

Чтобы понять, какие уникальные идентификаторы доступны на устройствах Android. Используйте это официальное руководство.

Рекомендации по использованию уникальных идентификаторов.

IMEI, адреса Mac, идентификатор экземпляра, идентификаторы GUID, SSAID, рекламный идентификатор, API сети безопасности для проверки устройств.

https://developer.android.com/training/articles/user-data-ids

person Waheed Nazir    schedule 03.05.2019

Теперь у Google есть рекламный идентификатор.
Он также может использоваться, но учтите, что:

Рекламный идентификатор - это уникальный сбрасываемый идентификатор, зависящий от пользователя.

а также

позволяет пользователям сбросить свой идентификатор или отказаться от рекламы на основе интересов в приложениях Google Play.

Таким образом, хотя этот идентификатор может измениться, похоже, что скоро у нас может не быть выбора, зависит от цели этого идентификатора.

Дополнительная информация @ develper.android

Скопируйте и вставьте сюда код

HTH

person Hertzel Guinness    schedule 02.11.2013
comment
Его можно сбросить: рекламный идентификатор - это уникальный, но сбрасываемый пользователем строковый идентификатор, который позволяет рекламным сетям и другим приложениям анонимно идентифицировать пользователя. - person Jared Burrows; 06.11.2013
comment
(@JaredBurrows да, это упоминается в посте ...) - person Hertzel Guinness; 06.11.2013

1. Используйте диспетчер телефонии, который предоставляет уникальный идентификатор (например, IMEI). См. Пример,

import android.telephony.TelephonyManager;
import android.content.Context;
// ...
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) getSystemService(Context.
                TELEPHONY_SERVICE);
/*
* getDeviceId() returns the unique device ID.
* For example,the IMEI for GSM and the MEID or ESN for CDMA phones.
*/
String deviceId = telephonyManager.getDeviceId();
/*
* getSubscriberId() returns the unique subscriber ID,
*/
String subscriberId = telephonyManager.getSubscriberId();

Это требует android.permission.READ_PHONE_STATE от вашего пользователя, что может быть трудно оправдать, следуя типу приложения, которое вы сделали.

  1. Устройства без услуг телефонии, такие как планшеты, должны сообщать уникальный идентификатор устройства, доступный через android.os.Build.SERIAL, начиная с Android 2.3 Gingerbread. Некоторые телефоны с услугами телефонии также могут определять серийный номер. Поскольку не все устройства Android имеют серийный номер, это решение ненадежно.

  2. При первой загрузке устройства генерируется и сохраняется случайное значение. Это значение доступно через Settings.Secure.ANDROID_ID. Это 64-битное число, которое должно оставаться постоянным на протяжении всего срока службы устройства. ANDROID_ID кажется хорошим выбором для уникального идентификатора устройства, поскольку он доступен для смартфонов и планшетов. Чтобы получить значение, вы можете использовать следующий код,

    Строка androidId = Settings.Secure.getString (getContentResolver (), Settings.Secure.ANDROID_ID);

Однако значение может измениться, если на устройстве будет выполнен сброс настроек до заводских. Также есть известная ошибка в популярном телефоне от производителя, где на каждом экземпляре есть одинаковый ANDROID_ID. Ясно, что решение не на 100% надежно.

  1. Используйте UUID. Поскольку требование для большинства приложений - идентифицировать конкретную установку, а не физическое устройство, хорошее решение для получения уникального идентификатора для пользователя, если использовать класс UUID. Следующее решение было представлено Рето Мейером из Google в презентации Google I / O:
SharedPreferences sharedPrefs = context.getSharedPreferences(
         PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);

Обновление: варианты №1 и №2 больше не доступны после Android 10 в связи с обновлениями конфиденциальности от Google. поскольку вариант 2 и 3 требует критического разрешения.

person Kiran Maniya    schedule 05.10.2018
comment
В каком телефоне у каждого экземпляра одинаковый ANDROID_ID? - person viper; 26.08.2019
comment
обратитесь к официальной документации developer.android.com/reference/ android / provider / - person Kiran Maniya; 26.08.2019
comment
DeviceInfoProvider не входит в Android SDK - person user924; 06.02.2020
comment
Спасибо, @ user924 за указание на это. Если у вас есть дополнительные сведения, вы можете отредактировать ответ, чтобы улучшить его. - person Kiran Maniya; 06.02.2020
comment
@KiranManiya Отредактируйте придуманный ответ. Как люди могут знать, как это редактировать, если вы это придумали? Это вы должны его редактировать. Не отвечайте здесь на вопрос своей иллюзией - person jerinho.com; 25.04.2020
comment
@jerinho Большое спасибо. Думаю, вы прошли оба моих ответа. - person Kiran Maniya; 26.04.2020

Идентификатор Mac устройства Android также является уникальным идентификатором. Он не изменится, даже если само устройство отформатировано.

Используйте следующий код, чтобы получить идентификатор Mac:

WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();

Кроме того, не забудьте добавить соответствующие разрешения в свой AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
person Baskaran Veerabathiran    schedule 03.10.2016
comment
К сожалению, это не сработает, если нет текущего Wi-Fi-соединения. Из документы (курсив добавлен ): Возвращать динамическую информацию о текущем Wi-Fi-соединении, если оно активно. - person Ted Hopp; 05.10.2016
comment
Также, предоставив root-доступ на устройстве, можно подделать MAC-адрес - person ; 03.07.2017
comment
Устройства под управлением Android 10 (уровень API 29) и выше передают рандомизированные MAC-адреса всем приложениям, которые не являются приложениями владельца устройства, поэтому он не будет уникальным, если вы используете Android версии 10 или выше. - person Saddan; 23.05.2020

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

https://android-developers.googleblog.com/2017/04/changes-to-device-identifiers-in.html

tl; dr Serial потребует разрешения ТЕЛЕФОНА, а идентификатор Android будет изменяться для разных приложений в зависимости от имени пакета и подписи.

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

https://developer.android.com/training/articles/user-data-ids.html

person bugraoral    schedule 11.04.2017

Обычно я использую уникальный идентификатор устройства для своих приложений. Но иногда пользуюсь IMEI. Оба номера уникальны.

чтобы получить IMEI (международный идентификатор мобильного оборудования)

public String getIMEI(Activity activity) {
    TelephonyManager telephonyManager = (TelephonyManager) activity
            .getSystemService(Context.TELEPHONY_SERVICE);
    return telephonyManager.getDeviceId();
}

чтобы получить уникальный идентификатор устройства

public String getDeviceUniqueID(Activity activity){
    String device_unique_id = Secure.getString(activity.getContentResolver(),
            Secure.ANDROID_ID);
    return device_unique_id;
}
person Zin Win Htet    schedule 19.06.2017

Я столкнулся с этим вопросом несколько лет назад и научился реализовывать обобщенное решение, основанное на различных ответах.

Я использовал обобщенное решение в течение нескольких лет в реальном продукте. Пока он мне служит очень хорошо. Вот фрагмент кода, основанный на различных ответах.

Обратите внимание, что getEmail большую часть времени будет возвращать null, поскольку мы не запрашивали разрешение явно.

private static UniqueId getUniqueId() {
    MyApplication app = MyApplication.instance();

    // Our prefered method of obtaining unique id in the following order.
    // (1) Advertising id
    // (2) Email
    // (2) ANDROID_ID
    // (3) Instance ID - new id value, when reinstall the app.

    ////////////////////////////////////////////////////////////////////////////////////////////
    // ADVERTISING ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    AdvertisingIdClient.Info adInfo = null;
    try {
        adInfo = AdvertisingIdClient.getAdvertisingIdInfo(app);
    } catch (IOException e) {
        Log.e(TAG, "", e);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e(TAG, "", e);
    } catch (GooglePlayServicesRepairableException e) {
        Log.e(TAG, "", e);
    }

    if (adInfo != null) {
        String aid = adInfo.getId();
        if (!Utils.isNullOrEmpty(aid)) {
            return UniqueId.newInstance(aid, UniqueId.Type.aid);
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // EMAIL
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String email = Utils.getEmail();
    if (!Utils.isNullOrEmpty(email)) {
        return UniqueId.newInstance(email, UniqueId.Type.eid);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // ANDROID ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String sid = Settings.Secure.getString(app.getContentResolver(), Settings.Secure.ANDROID_ID);
    if (!Utils.isNullOrEmpty(sid)) {
        return UniqueId.newInstance(sid, UniqueId.Type.sid);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////
    // INSTANCE ID
    ////////////////////////////////////////////////////////////////////////////////////////////
    final String iid = com.google.android.gms.iid.InstanceID.getInstance(MyApplication.instance()).getId();
    if (!Utils.isNullOrEmpty(iid)) {
        return UniqueId.newInstance(iid, UniqueId.Type.iid);
    }

    return null;
}

public final class UniqueId implements Parcelable {
    public enum Type implements Parcelable {
        aid,
        sid,
        iid,
        eid;

        ////////////////////////////////////////////////////////////////////////////
        // Handling Parcelable nicely.

        public static final Parcelable.Creator<Type> CREATOR = new Parcelable.Creator<Type>() {
            public Type createFromParcel(Parcel in) {
                return Type.valueOf(in.readString());
            }

            public Type[] newArray(int size) {
                return new Type[size];
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeString(this.name());
        }

        // Handling Parcelable nicely.
        ////////////////////////////////////////////////////////////////////////////
    }

    public static boolean isValid(UniqueId uniqueId) {
        if (uniqueId == null) {
            return false;
        }
        return uniqueId.isValid();
    }

    private boolean isValid() {
        return !org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) && type != null;
    }

    private UniqueId(String id, Type type) {
        if (org.yccheok.jstock.gui.Utils.isNullOrEmpty(id) || type == null) {
            throw new java.lang.IllegalArgumentException();
        }
        this.id = id;
        this.type = type;
    }

    public static UniqueId newInstance(String id, Type type) {
        return new UniqueId(id, type);
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + id.hashCode();
        result = 31 * result + type.hashCode();
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof UniqueId)) {
            return false;
        }

        UniqueId uniqueId = (UniqueId)o;
        return this.id.equals(uniqueId.id) && this.type == uniqueId.type;
    }

    @Override
    public String toString() {
        return type + ":" + id;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Handling Parcelable nicely.

    public static final Parcelable.Creator<UniqueId> CREATOR = new Parcelable.Creator<UniqueId>() {
        public UniqueId createFromParcel(Parcel in) {
            return new UniqueId(in);
        }

        public UniqueId[] newArray(int size) {
            return new UniqueId[size];
        }
    };

    private UniqueId(Parcel in) {
        this.id = in.readString();
        this.type = in.readParcelable(Type.class.getClassLoader());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(this.id);
        parcel.writeParcelable(this.type, 0);
    }

    // Handling Parcelable nicely.
    ////////////////////////////////////////////////////////////////////////////

    public final String id;
    public final Type type;
}

public static String getEmail() {
    Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
    AccountManager accountManager = AccountManager.get(MyApplication.instance());
    Account[] accounts = accountManager.getAccountsByType("com.google");
    for (Account account : accounts) {
        if (emailPattern.matcher(account.name).matches()) {
            String possibleEmail = account.name;
            return possibleEmail;
        }
    }

    accounts = accountManager.getAccounts();
    for (Account account : accounts) {
        if (emailPattern.matcher(account.name).matches()) {
            String possibleEmail = account.name;
            return possibleEmail;
        }
    }

    return null;
} 
person Cheok Yan Cheng    schedule 07.11.2017
comment
Но работает ли это, когда пользователь перезагружает свой телефон? В этом случае идентификатор Android будет изменен, идентификатор рекламы и электронная почта тоже будут сброшены. - person G3n1t0; 09.03.2021

Не рекомендуется, так как deviceId можно использовать для отслеживания в сторонних руках, но это другой способ.

@SuppressLint("HardwareIds")
private String getDeviceID() {
    deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(),
                    Settings.Secure.ANDROID_ID);
    return deviceId;
}
person Ege Kuzubasioglu    schedule 28.12.2017
comment
Android вносит некоторые изменения в: Settings.Secure.ANDROID_ID; В Android 8.0 (уровень API 26) и более поздних версиях платформы - 64-битное число (выраженное в виде шестнадцатеричной строки), уникальное для каждой комбинации ключа подписи приложения, пользователя и устройства. Это означает, что Settings.Secure.ANDROID_ID теперь возвращает идентификаторы, уникальные для комбинации приложение / устройство, что делает работу более безопасной для пользователя. - person Jeff Padgett; 22.06.2018

Вот простой ответ, чтобы получить AAID, протестировано, работает правильно, июнь 2019 г.

 AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String token = null;
            Info adInfo = null;
            try {
                adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
            } catch (IOException e) {
                // ...
            } catch ( GooglePlayServicesRepairableException e) {
                // ...
            } catch (GooglePlayServicesNotAvailableException e) {
                // ...
            }
            String android_id = adInfo.getId();
            Log.d("DEVICE_ID",android_id);

            return android_id;
        }

        @Override
        protected void onPostExecute(String token) {
            Log.i(TAG, "DEVICE_ID Access token retrieved:" + token);
        }

    };
    task.execute();

прочтите полный ответ подробно здесь:

person Raj    schedule 11.06.2019

Получите D UUID устройства, номер модели с названием бренда и его номер версии с помощью функции ниже.

Работает в Android 10 безупречно, и вам не нужно разрешать чтение состояния телефона.

Фрагменты кода:

private void fetchDeviceInfo() {
    String uniquePseudoID = "35" +
            Build.BOARD.length() % 10 +
            Build.BRAND.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 serial = Build.getRadioVersion();
    String uuid=new UUID(uniquePseudoID.hashCode(), serial.hashCode()).toString();
    String brand=Build.BRAND;
    String modelno=Build.MODEL;
    String version=Build.VERSION.RELEASE;
    Log.e(TAG, "fetchDeviceInfo: \n "+
            "\n uuid is : "+uuid+
            "\n brand is: "+brand+
            "\n model is: "+modelno+
            "\n version is: "+version);
}

Вызовите вышеуказанную функцию и проверьте вывод вышеуказанного кода. пожалуйста, просмотрите свой лог-кот в студии Android. Это выглядит примерно так:

введите здесь описание изображения

person CodeInsideCoffee    schedule 07.06.2020
comment
что такое% 10 и 35 + ... в вашем коде? я имею в виду, почему вы используете этот подход для создания уникального идентификатора? почему бы просто не объединить эти строки и сгенерировать уникальный UUID? вывод этого метода полностью уникален для всех устройств в мире? - person porya74; 15.06.2020

Чтобы включить Android 9, у меня есть только одна идея, которая (вероятно) не нарушает никаких условий, не требует разрешений и работает с разными установками и приложениями.

Отпечатки пальцев на сервере должны позволять однозначно идентифицировать устройство. Сочетание информации об оборудовании + установленных приложений и времени установки должно помочь. Время первой установки не изменится, если приложение не будет удалено и снова установлено. Но это необходимо сделать для всех приложений на устройстве, чтобы они не могли идентифицировать устройство (например, после сброса настроек).

Вот как я бы это сделал:

  1. Извлеките информацию об оборудовании, названиях пакетов приложений и времени первой установки.

Вот как вы извлекаете все приложения из Android (разрешения не требуются):

final PackageManager pm = application.getPackageManager();
List<ApplicationInfo> packages = 
pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo packageInfo : packages) {
    try {
        Log.d(TAG, "Installed package :" + packageInfo.packageName);
        Log.d(TAG, "Installed :" + pm.getPackageInfo(packageInfo.packageName, 0).firstInstallTime);
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
}
  1. Вы можете захотеть создать хэш для каждой комбинации имени пакета и метки времени установки, прежде чем отправлять ее на сервер, поскольку это может или не может быть связано с вашим бизнесом, что пользователь установил на устройстве.
  2. Некоторые приложения (на самом деле их много) являются системными. Скорее всего, они будут иметь одинаковую метку времени установки, соответствующую последнему обновлению системы после сброса к заводским настройкам. Поскольку они имеют одинаковую метку времени установки, они не могут быть установлены пользователем и могут быть отфильтрованы.
  3. Отправьте информацию на сервер и позвольте ему найти ближайшее совпадение среди ранее сохраненной информации. Вам необходимо установить порог при сравнении с ранее сохраненной информацией об устройстве по мере установки и удаления приложений. Но я предполагаю, что этот порог может быть очень низким, поскольку любое сочетание имени пакета и отметки времени первой установки само по себе будет довольно уникальным для устройства, а приложения не так часто устанавливаются и удаляются. Наличие нескольких приложений только увеличивает вероятность быть уникальным.
  4. Верните сгенерированный уникальный идентификатор для соответствия или сгенерируйте уникальный идентификатор, сохраните с информацией об устройстве и верните этот новый идентификатор.

NB: это непроверенный и непроверенный метод! Я уверен, что это сработает, но я также почти уверен, что, если это приживется, они так или иначе закроют его.

person Jens Vesti    schedule 31.01.2019

Если вы добавите:

Settings.Secure.getString(context.contentResolver,
    Settings.Secure.ANDROID_ID)

Android Lint выдаст следующее предупреждение:

Не рекомендуется использовать getString для получения идентификаторов устройств. Информация для проверки: использование этих идентификаторов устройств не рекомендуется, кроме как для предотвращения крупного мошенничества и сложных случаев использования телефонии. Для рекламных случаев используйте AdvertisingIdClient $ Info # getId, а для аналитики - InstanceId # getId.

Поэтому вам следует избегать этого.

Как указано в документации для разработчиков Android :

1: Избегайте использования идентификаторов оборудования.

В большинстве случаев вы можете избежать использования аппаратных идентификаторов, таких как SSAID (Android ID) и IMEI, без ограничения необходимой функциональности.

2. Используйте рекламный идентификатор только для профилирования пользователей или вариантов использования рекламы.

При использовании рекламного идентификатора всегда уважайте выбор пользователей в отношении отслеживания рекламы. Кроме того, убедитесь, что идентификатор не может быть связан с информацией, позволяющей установить личность (PII), и избегайте параллельного сброса идентификатора рекламы.

3. По возможности используйте идентификатор экземпляра или GUID, хранящийся в частном порядке, для всех других случаев использования, кроме предотвращения мошенничества с платежами и телефонной связи.

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

4. Используйте API-интерфейсы, подходящие для вашего варианта использования, чтобы минимизировать риск конфиденциальности.

Используйте DRM API для защиты ценных материалов и API SafetyNet для защиты от злоупотреблений. API-интерфейсы SafetyNet - это самый простой способ определить, является ли устройство подлинным, без риска для конфиденциальности.

person Malwinder Singh    schedule 24.07.2019

String SERIAL_NUMER = Build.SERIAL;

Возвращает СЕРИЙНЫЙ НОМЕР в виде строки, уникальной для каждого устройства.

person Jeffy    schedule 07.09.2017

Серийный номер - это уникальный идентификатор устройства, доступный через android.os.Build.SERIAL.

public static String getSerial() {
    String serial = "";
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
        serial = Build.getSerial();
    }else{ 
        serial = Build.SERIAL;    
    }
    return serial;
}

Перед вызовом getSerial () убедитесь, что у вас есть разрешение READ_PHONE_STATE.

ПРИМЕЧАНИЕ. - Недоступно для устройств без телефонии (например, планшетов только с Wi-Fi).

person shivampip    schedule 14.12.2017
comment
Обратите внимание, что в документации говорится, что это вернет серийный номер оборудования , если он доступен, предполагая, что Build.SERIAL (или Build.getSerial()) не всегда доступен. Дополнительная информация доступна в сообщении блога Изменения в Идентификаторы устройств в Android O. Также стоит прочитать: Рекомендации по использованию уникальных идентификаторов. - person Ted Hopp; 14.12.2017

Для полноты, вот как вы можете получить Id в Xamarin.Android и C #:

var id = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);

Или, если вы не в Activity:

var id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId);

Где context - это переданный контекст.

person Martin Zikmund    schedule 21.01.2019

android.telephony.TelephonyManager.getDeviceId()

Это вернет любую строку, однозначно идентифицирующую устройство (IMEI в GSM, MEID для CDMA).

Вам понадобится следующее разрешение в вашем AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
person Anubhav    schedule 25.09.2019
comment
Устарело - person Googlian; 23.10.2019

Да, у каждого устройства Android есть уникальный серийный номер, который можно узнать из этого кода. Build.SERIAL. Обратите внимание, что он был добавлен только в API уровня 9 и может присутствовать не на всех устройствах. Чтобы получить уникальный идентификатор на более ранних платформах, вам нужно будет прочитать что-то вроде MAC-адреса или IMEI.

person Stephan John    schedule 11.09.2019

Проверьте SystemInfo.deviceUniqueIdentifier

Документация: http://docs.unity3d.com/Documentation/ScriptReference/SystemInfo-deviceUniqueIdentifier.html

Уникальный идентификатор устройства. Гарантия уникальности для каждого устройства (только чтение).

iOS: на устройствах до iOS7 возвращается хэш MAC-адреса. На устройствах iOS7 это будет UIDevice identifierForVendor или, если это не удается по какой-либо причине, ASIdentifierManager AdvertisingIdentifier.

person Ciul    schedule 06.01.2014

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

person TootsieRockNRoll    schedule 21.10.2013
comment
Идея состоит в том, чтобы иметь идентификатор, который пережил бы удаление и повторную установку приложения. Сохранение идентификатора в базе данных не помогает, потому что база данных удаляется при удалении приложения. - person Ted Hopp; 21.10.2013

Чтобы получить идентификатор пользователя, вы можете использовать библиотеку лицензирования Google Play.

Чтобы загрузить эту библиотеку, откройте SDK Manager => SDK Tools. Путь к загруженным файлам библиотеки:

path_to_android_sdk_on_your_pc / extras / google / market_licensing / library

Включите библиотеку в свой проект (вы можете просто скопировать ее файлы).

Далее вам понадобится реализация интерфейса Policy (вы можете просто использовать один из двух файлов из библиотеки: ServerManagedPolicy или StrictPolicy).

Идентификатор пользователя будет предоставлен вам внутри processServerResponse() функции:

public void processServerResponse(int response, ResponseData rawData) {
    if(rawData != null) {
        String userId = rawData.userId
        // use/save the value
    }
    // ...
}

Затем вам нужно создать LicenseChecker с политикой и вызвать функцию checkAccess(). Используйте MainActivity.java в качестве примера того, как это сделать. MainActivity.java находится внутри этой папки:

path_to_android_sdk_on_your_pc / extras / google / market_licensing / sample / src / com / example / android / market / licensing

Не забудьте добавить разрешение CHECK_LICENSE к вашему AndroidManifest.xml.

Подробнее о библиотеке лицензирования: https://developer.android.com/google/play/licensing

person Vitaly Zinchenko    schedule 03.08.2019

Android ограничивает идентификатор, связанный с оборудованием, после Android O, поэтому Android_Id является решением для уникального идентификатора, но у него есть проблема, когда отражатель устройства генерирует новый android_id, чтобы преодолеть эту проблему, мы можем использовать DRUMID.

val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
val drumIDByteArray = MediaDrm(WIDEVINE_UUID).getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)

val drumID = android.util.Base64.encodeToString(drumIDByteArray,android.util.Base64.DEFAULT)
person jai khambhayta    schedule 19.05.2020

Вы получите MAC-адрес Wi-Fi, используя следующий код, независимо от того, использовали ли вы случайный адрес при попытке подключиться к Wi-Fi или нет, и независимо от того, был ли Wi-Fi включен или выключен.

Я использовал метод из приведенной ниже ссылки и добавил небольшую модификацию, чтобы получить точный адрес вместо рандомизированного:

Получение MAC-адреса в Android 6.0

public static String getMacAddr() {
StringBuilder res1 = new StringBuilder();
try {
List<NetworkInterface> all =     
Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {    
if (!nif.getName().equalsIgnoreCase("p2p0")) continue;

        byte[] macBytes = nif.getHardwareAddress();
        if (macBytes == null) {
            continue;
        }

        res1 = new StringBuilder();
        for (byte b : macBytes) {
            res1.append(String.format("%02X:",b));
        }

        if (res1.length() > 0) {
            res1.deleteCharAt(res1.length() - 1);
        }
    }
} catch (Exception ex) {
}
return res1.toString();

}

person Abdallah AlTaher    schedule 23.09.2020