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




как узнать id телефона леново (24)

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


Более конкретно Settings.Secure.ANDROID_ID. Это 64-разрядное количество, которое генерируется и сохраняется при первом загрузке устройства. Он сбрасывается при стирании устройства.

ANDROID_IDкажется хорошим выбором для уникального идентификатора устройства. Есть недостатки: во-первых, он не на 100% надежен в выпусках Android до 2.2. (“Froyo”).Кроме того, в популярном мобильном телефоне был обнаружен хотя бы один широко распространенный телефон от крупного производителя, где каждый экземпляр имеет тот же ANDROID_ID.


Идентификатор Mac устройства Android также является уникальным идентификатором, он не изменится, если мы отформатируем само устройство, используя следующий код, чтобы получить идентификатор mac id

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

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


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

private static String uniqueID = null;
private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";

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

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


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

С помощью:

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

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

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

У моего устройства нет сотовой радиосвязи.


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

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

[email protected]:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
[email protected]:~$ 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
  • Mini MK802
  • Samsung Galaxy S II

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


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

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

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

Он вернет что-то вроде этого: 551F27C060712A72730B0A0F734064B1

Примечание. Вы всегда можете добавить больше longIdстрок в строку. Например, Serial #. беспроводной адаптер адрес. 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 "";
}

Следующий код возвращает серийный номер устройства с помощью скрытого API Android. Но этот код не работает на вкладке 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) {

}

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


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

Псевдо-уникальный идентификатор, который работает на всех устройствах Android. На некоторых устройствах нет телефона (например, планшеты) или по какой-то причине вы не хотите включать разрешение READ_PHONE_STATE. Вы все еще можете читать такие данные, как ПЗУ, имя производителя, тип ЦП и другие детали оборудования, которые будут хорошо подходить, если вы хотите использовать идентификатор для проверки серийного ключа или других общих целей. Идентификатор, вычисленный таким образом, не будет уникальным: можно найти два устройства с одинаковым ID (на основе одного и того же аппаратного и ROM-изображения), но изменения в реальных приложениях незначительны. Для этого вы можете использовать класс 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), чтобы иметь тот же ID размера, что и IMEI (15 цифр). Здесь есть и другие возможности, просто взгляните на эти строки. Возвращает что-то вроде 355715565309247. Никакого специального разрешения не требуется, поэтому этот подход очень удобен.

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


Для аппаратного распознавания определенного устройства 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 не включен.

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


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

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

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


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

Полное раскрытие: мое приложение первоначально использовало подход ниже, но больше не использует этот подход, и теперь мы используем подход, описанный в записи android-developers.blogspot.com/2011/03/… который ссылается на ответ emmby (а именно, генерирование и сохранение UUID#randomUUID() ).

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

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

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

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

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

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

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

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

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

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

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

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

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

public class MyBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,          PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

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

BackupManager backupManager = new BackupManager(context);

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

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

            //backup the changes
            BackupManager mBackupManager = new BackupManager(context);
            mBackupManager.dataChanged();
        }
    }

    return uniqueID;
}

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

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

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


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

Идентификатор рекламы - это уникальный уникальный идентификатор

а также

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

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

http://developer.android.com/google/play-services/id.html

Копировать-вставить код здесь

НТН


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

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

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

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

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

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

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

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

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

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

  • Пользователи могут стереть / изменить свой ПЗУ, если они укоренены
  • Вы можете отслеживать пользователей на разных платформах (iOS, Android, Windows и Web)
  • Лучше всего хотеть ОТПРАВИТЬ ИНДИВИДУАЛЬНОГО ПОЛЬЗОВАТЕЛЯ с их согласия - просто попросить их войти (сделать это без использования 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 unique ID of build information (may overlap data - API < 9)

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

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

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

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

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

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

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

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

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

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

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

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

API> = 9:

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

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

API <9:

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

Если все остальное терпит неудачу:

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

Изменения:

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

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

/**
 * Return pseudo unique ID
 * @return ID
 */
public static String getUniquePsuedoID() {
    // If all else fails, if the user does have lower than API 9 (lower
    // than Gingerbread), has reset their device or 'Secure.ANDROID_ID'
    // returns 'null', then simply the ID returned will be solely based
    // off their Android device information. This is where the collisions
    // can happen.
    // Thanks http://www.pocketmagic.net/?p=1662!
    // Try not to use DISPLAY, HOST or ID - these items could change.
    // If there are collisions, there will be overlapping data
    String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);

    // Thanks to @Roman SL!
    // https://.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://.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();
}

Источник / Docs:

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

Важный:

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

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

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

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

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

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


Я использую следующий код, чтобы получить 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);


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


В официальном блоге разработчиков Android теперь есть полная статья именно по этому вопросу, « android-developers.blogspot.com/2011/03/… .





uniqueidentifier