Як знайти серійний номер пристрою Android?


115

Мені потрібно використовувати унікальний ідентифікатор для програми Android, і я вважав, що серійний номер пристрою буде хорошим кандидатом. Як отримати серійний номер пристрою Android у своєму додатку?


2
Не забудьте додати android: name = "android.permission.READ_PHONE_STATE" до свого маніфесту
Michael SIlveus


Якщо ви хочете отримати унікальний ідентифікатор без дозволів, ви можете використовувати цю бібліотеку для створення або унікального ідентифікатора на пристрій з Identity.getDeviceId (контекст), або ідентифікатора для встановлення вашого додатка через Identity.getInstallationId (контекст) .
каре

Відповіді:


105
TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

getSystemService - метод з класу Activity. getDeviceID () поверне MDN або MEID пристрою залежно від того, яке радіо використовує телефон (GSM або CDMA).

Кожен пристрій ПОВИНЕН повернути тут унікальне значення (якщо припустити, що це телефон). Це повинно працювати для будь-якого пристрою Android із сим-слотом або радіо CDMA. Ви самостійно використовуєте цю мікрохвильову піч на Android ;-)


@Hasemam Це не працює для мене, а помилка "Force Close"
Paresh Mayani

23
@Hasemam працює нормально вже після додавання <використання-дозволу android: name = "android.permission.READ_PHONE_STATE"> </uses-permission> дозволу у файл androidManifest.xml.
Paresh Mayani

23
Офіційний блог розробника Android щодо використання цього ідентифікатора
містить поради

8
окрім мікрохвильової печі, що працює на Android, а що стосується планшетного ПК, що працює на Android? :)
ajacian81

21
Цього методу слід уникати, це працюватиме на телефонах, але не працюватиме на пристроях без телефонної мікросхеми (приклад - планшети). З 2.3 ви можете використовувати android.os.Build.SERIAL, але перегляньте блог розробників, який @DavidCaunt запропонував.
Джон Мітчелл

71

Як зазначає Дейв Вебб, у блозі розробників Android є стаття, яка висвітлює цю проблему.

Я спілкувався з кимось із Google, щоб отримати додаткові роз'яснення щодо кількох питань. Ось що я виявив, що НЕ згадується у вищезгаданому дописі в блозі:

  • ANDROID_ID є кращим рішенням. ANDROID_ID ідеально надійний у версіях Android <= 2.1 або> = 2.3. Лише у 2.2 є проблеми, про які йдеться у публікації.
  • Помилка ANDROID_ID у версії 2.2 впливає на кілька пристроїв кількох виробників.
  • Наскільки мені вдалося визначити, усі постраждалі пристрої мають однаковий ANDROID_ID , який становить 9774d56d682e549c . Це також той самий ідентифікатор пристрою, про який повідомляв емулятор, btw.
  • Google вважає, що OEM-виробники виправили цю проблему для багатьох або більшості своїх пристроїв, але мені вдалося переконатися, що станом на початок квітня 2011 року, як мінімум, все ще досить легко знайти пристрої, які зламали ANDROID_ID.

Виходячи з рекомендацій Google, я реалізував клас, який генеруватиме унікальний UUID для кожного пристрою, використовуючи ANDROID_ID як насіння, де це доречно, повертаючись на TelephonyManager.getDeviceId () за необхідності, і якщо це не вдається, вдаючись до випадково створеного унікального 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 static volatile 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;
    }
}

1
Які дозволи потрібні додатку, щоб використовувати це?
Дейв Л.

1
<використання-дозволу android: name = "android.permission.READ_PHONE_STATE"> </uses-permission>
Габріель

1
@ ef2011 - це двічі перевірений шаблон блокування: en.wikipedia.org/wiki/Double-
Managed_locking

3
Дякуємо за публікацію Але що зупинити когось із вкоріненим телефоном від простого редагування device_id.xml, щоб ввести новий UUID за власним вибором? . В іншому випадку немає необхідності зберігати це між запуском програми; безпечніше повторно генерувати.
Карлос П

1
«ANDROID_ID» є кращим рішенням »Зверніть увагу , що ANDROID_ID більше не однозначно ідентифікує пристрій :. Stackoverflow.com/a/13465373/150016
Том

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

Цей код повертає серійний номер пристрою за допомогою прихованого API Android.


7
це просто дає мені те саме значення, що і те, що я отримую з android.os.Build.SERIAL
Йозеф

Я помиляюся, чи цей серійний номер однаковий у всіх пристроях із певним користувацьким ромом? Серійний номер мого пристрою (у пристрої запуску пристроїв затемнення) відображає 01234567890ABC для телефону із користувацькою шиною.
Peterdk

@Peterdk на моєму пристрої з ціаногеном-9 обидва способи (до andy-9, як у відповіді та легший, доступний від andy-9 on) повідомляють про правильність s / n (те саме, що на наклейці виробника). Однак це може залежати від конкретної спеціалізованої версії rom. Який rom / версія ви використовуєте?
morgwai

16
String deviceId = Settings.System.getString(getContentResolver(),
                                Settings.System.ANDROID_ID);

Хоча, не гарантується, що Android ID буде унікальним ідентифікатором.


@Paresh Mayani, Важко сказати, що може бути проблемою, не дивлячись на код. Моє єдине припущення - getContentResolverце повернення null. Однак, можливо, варто буде відкрити запитання та опублікувати свій код.
Ентоні Форлоні

4
Цей ідентифікатор походить з облікового запису Google, пов’язаного з телефоном. Симулятор, як правило, не має. У справжнього телефону теж може бути немає. Крім того, це документально підтверджено як "може змінитися після скидання до заводських налаштувань", і його можна довільно змінити в будь-який час на вкоріненому телефоні. Використовуйте на свій страх і ризик. Немає хорошої альтернативи - інші орієнтовні ідентифікатори пристрою або не є загальнодоступними, або не є унікальними, або обидва. Дивіться інші відповіді на решту цієї сумної історії.
Сева Алексєєва

14

У блозі Android Developer є чудова публікація, в якій обговорюється це питання .

Він рекомендує не використовувати, TelephonyManager.getDeviceId()оскільки він не працює на пристроях Android, які не є телефонами, такими як планшети, це вимагаєREAD_PHONE_STATE дозволу, і він не працює надійно на всіх телефонах.

Натомість ви можете використовувати одне з наступних:

  • Адреса Mac
  • Серійний номер
  • ANDROID_ID

У публікації обговорюються плюси і мінуси кожного, і його варто прочитати, щоб ви могли розібратися, що було б найкращим для вашого використання.


+1, привіт Дейв, дякую за уточнення, тому що зараз я розробляю програму для планшета, де мені потрібно мати унікальний ідентифікатор пристрою Android, і що мені потрібно використовувати, щоб отримати унікальний планшетний пристрій Android?
Paresh Mayani

12

Для простого номера, яке є унікальним для пристрою та постійним протягом його життя (забороняється скинути заводські налаштування чи зламати), використовуйте Settings.Secure.ANDROID_ID .

String id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);

Щоб використовувати серійний номер пристрою (той, який відображений у розділі "Налаштування системи / Про систему / Стан"), якщо він доступний, і повернутися до Android ID:

String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);

пряма відповідь !!
faris faris

Збудовано.SERİAL застаріло в
Яві

7

IMEI хороший, але працює лише на пристроях Android з телефоном. Слід також врахувати підтримку планшетів та інших пристроїв Android, у яких немає телефону.

У вас є такі варіанти, як: Створення членів класу, BT MAC, WLAN MAC або ще краще - поєднання всього цього.

Я пояснив ці деталі у статті в своєму блозі, див .: http://www.pocketmagic.net/?p=1662


6

Оскільки жодна відповідь тут не згадує про ідеальний ідентифікаційний код, який є ПЕРСИСТИЧНИМ через системні оновлення та існує на ВСІХ пристроях (головним чином через те, що немає індивідуального рішення від Google), я вирішив опублікувати метод, який є наступне найкраще - поєднуючи два доступні ідентифікатори та перевіряючи вибір між ними під час виконання.

Перед кодом, 3 факти:

  1. TelephonyManager.getDeviceId()(akaIMEI) не працюватиме добре або зовсім не для пристроїв без GSM, 3G, LTE тощо, але завжди повертатиме унікальний ідентифікатор за наявності відповідного обладнання , навіть коли SIM-картки не вставлено або навіть коли немає слота SIM-карти ( деякі виробники оригіналу зробили це).

  2. Оскільки Gingerbread (Android 2.3) android.os.Build.SERIAL повинен існувати на будь-якому пристрої, що не забезпечує IMEI , тобто не має вищезазначеного обладнання, відповідно до політики Android.

  3. Через факт (2.), щонайменше один із цих двох унікальних ідентифікаторів завжди буде присутній , і SERIAL може бути присутнім одночасно з IMEI.

Примітка. Факти (1.) та (2.) ґрунтуються на твердженнях Google

РІШЕННЯ

З наведеними вище фактами, завжди можна мати унікальний ідентифікатор, перевіривши, чи є апаратне забезпечення, пов'язане з IMEI, і повернутися до SERIAL, коли його немає, оскільки не можна перевірити, чи дійсна СЕРІАЛ дійсна. У наведеному нижче статичному класі представлені два методи перевірки такої присутності та використання або IMEI, або СЕРІАЛ:

import java.lang.reflect.Method;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;

public class IDManagement {

    public static String getCleartextID_SIMCHECK (Context mContext){
        String ret = "";

        TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

        if(isSIMAvailable(mContext,telMgr)){
            Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId());
            return telMgr.getDeviceId();

        }
        else{
            Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);

//          return Settings.Secure.ANDROID_ID;
            return android.os.Build.SERIAL;
        }
    }


    public static String getCleartextID_HARDCHECK (Context mContext){
        String ret = "";

        TelephonyManager telMgr = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        if(telMgr != null && hasTelephony(mContext)){           
            Log.i("DEVICE UNIQUE IDENTIFIER",telMgr.getDeviceId() + "");

            return telMgr.getDeviceId();    
        }
        else{
            Log.i("DEVICE UNIQUE IDENTIFIER", Settings.Secure.ANDROID_ID);

//          return Settings.Secure.ANDROID_ID;
            return android.os.Build.SERIAL;
        }
    }


    public static boolean isSIMAvailable(Context mContext, 
            TelephonyManager telMgr){

        int simState = telMgr.getSimState();

        switch (simState) {
        case TelephonyManager.SIM_STATE_ABSENT:
            return false;
        case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
            return false;
        case TelephonyManager.SIM_STATE_PIN_REQUIRED:
            return false;
        case TelephonyManager.SIM_STATE_PUK_REQUIRED:
            return false;
        case TelephonyManager.SIM_STATE_READY:
            return true;
        case TelephonyManager.SIM_STATE_UNKNOWN:
            return false;
        default:
            return false;
        }
    }

    static public boolean hasTelephony(Context mContext)
    {
        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null)
            return false;

        //devices below are phones only
        if (Build.VERSION.SDK_INT < 5)
            return true;

        PackageManager pm = mContext.getPackageManager();

        if (pm == null)
            return false;

        boolean retval = false;
        try
        {
            Class<?> [] parameters = new Class[1];
            parameters[0] = String.class;
            Method method = pm.getClass().getMethod("hasSystemFeature", parameters);
            Object [] parm = new Object[1];
            parm[0] = "android.hardware.telephony";
            Object retValue = method.invoke(pm, parm);
            if (retValue instanceof Boolean)
                retval = ((Boolean) retValue).booleanValue();
            else
                retval = false;
        }
        catch (Exception e)
        {
            retval = false;
        }

        return retval;
    }


}

Я б порадив використовувати getCleartextID_HARDCHECK. Якщо відображення не залишається у вашому оточенні, використовуйтеgetCleartextID_SIMCHECK методом, але врахуйте, що він повинен бути адаптований до ваших потреб SIM-присутності.

PS : Зауважте, що OEM-виробникам вдалося виправити SERIAL проти політики Google (декілька пристроїв із тим же SERIAL), а Google, як заявлено, має принаймні один відомий випадок у великому OEM (не розголошується, і я не знаю, яка марка це або, я здогадуюсь Samsung).

Відмова від відповідальності : Це відповідає на початковий питання про отримання унікального ідентифікатора пристрою, але ОП вніс неоднозначність, заявивши, що йому потрібен унікальний ідентифікатор для додатка. Навіть якщо для таких сценаріїв Android_ID буде кращим, він НЕ ПРАЦЮЄ після, скажімо, титанової резервної копії програми через 2 різні встановлення ROM (може бути навіть однаковий ROM). Моє рішення підтримує стійкість, яка не залежить від спалаху чи скидання на заводські налаштування, і вийде з ладу лише тоді, коли підробка IMEI або СЕРІЙНИЙ підробляється через хаки / апаратні моди.


5

Існують проблеми з усіма перерахованими вище підходами. У системі 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>

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

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

Для отримання додаткової інформації про цей підхід див. Розмову Reto тут http://www.google.com/events/io/2011/sesions/android-protips-advanced-topics-for-expert-android-app-developers.html

А докладні відомості про те, як реалізувати агент резервного копіювання, див. Тут на веб-сайті розробника: http://developer.android.com/guide/topics/data/backup.html Я особливо рекомендую тестувати розділ внизу, як це робить резервна копія. не відбуватись миттєво, і тому для тестування вам доведеться змусити створити резервну копію.


2

Інший спосіб - використовувати / 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

Ви також можете побачити моє повідомлення в блозі тут: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html, де я обговорюю, які інші файли доступні для отримання інформації.


Дякуємо, що опублікували свою відповідь! Будь ласка, уважно прочитайте FAQ щодо самореклами . Також зауважте, що Ви зобов’язуєтесь публікувати відмову щоразу, коли Ви посилаєтесь на власний сайт / продукт.
Ендрю Барбер

1

Як говорить @haserman:

TelephonyManager tManager = (TelephonyManager)myActivity.getSystemService(Context.TELEPHONY_SERVICE);
String uid = tManager.getDeviceId();

Але необхідно включити дозвіл у файл маніфесту:

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

1

Унікальний ідентифікатор пристрою пристрою Android OS як String.

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 ::

Визначення установок додатків


1

Build.SERIALце найпростіший шлях, хоча і не зовсім надійний, оскільки він може бути порожнім або іноді повертати інше значення ( доказ 1 , доказ 2 ), ніж те, що ви можете бачити в налаштуваннях свого пристрою.

Існує кілька способів отримати цю кількість залежно від виробника пристрою та версії Android, тому я вирішив зібрати всі можливі рішення, які я міг знайти в одній суті . Ось спрощена його версія:

public static String getSerialNumber() {
    String serialNumber;

    try {
        Class<?> c = Class.forName("android.os.SystemProperties");
        Method get = c.getMethod("get", String.class);

        serialNumber = (String) get.invoke(c, "gsm.sn1");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "ril.serialnumber");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "ro.serialno");
        if (serialNumber.equals(""))
            serialNumber = (String) get.invoke(c, "sys.serialnumber");
        if (serialNumber.equals(""))
            serialNumber = Build.SERIAL;

        // If none of the methods above worked
        if (serialNumber.equals(""))
            serialNumber = null;
    } catch (Exception e) {
        e.printStackTrace();
        serialNumber = null;
    }

    return serialNumber;
}

0

Я знаю, що це питання давнє, але його можна виконати в одному рядку коду

String deviceID = Build.SERIAL;


AFAIK, це зміниться після оновлення ОС пристрою, наприклад, з 4.4.2 до 4.4.4 або будь-якого іншого.
Den Drobiazko

-1

Я знайшов приклад класу, розміщеного @emmby вище, відмінною відправною точкою. Але він має пару недоліків, про що згадують інші афіші. Найважливішим є те, що він зберігає UUID у файлі XML без необхідності, після чого завжди отримує його з цього файлу. Це закладає клас відкритим для легкого злому: кожен, хто має вкорінений телефон, може редагувати XML-файл, щоб дати собі новий UUID.

Я оновив код так, що він зберігається до XML лише в разі крайньої необхідності (тобто при використанні випадково згенерованого UUID) і повторно врахував логіку відповідно до відповіді @Brill Pappin:

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 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) || (androidId == null) ) {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

                                if (deviceId != null)
                                {
                                    uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
                                }
                                else
                                {
                                    uuid = UUID.randomUUID();

                                    // Write the value out to the prefs file so it persists
                                    prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
                                }
                            }
                            else
                            {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                            } 
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }



                    }

                }
            }
        }

    }


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

Введення ідентифікатора в спільні префікси компрометує початкову мету отримати справді унікальний ідентифікатор. Наприклад, якщо ви хочете використовувати цей ідентифікатор як ключ для деяких обмежень, ви будете накручені, коли кваліфіковані користувачі викоріняють пристрій та отримають доступ до спільного файлу налаштувань. Його вміст може бути скопійовано, що означає ...
Євген Векслер

Є також ще одна помилка у відповіді MB і ваша. Якщо ви використовуєте randomUUID як deviceID і appID, він працює на всіх пристроях через плату, незалежно від того, чи це телефони чи ні, чи вони є пристроями google exp чи ні.
Фред Гротт

-2

Так. Це серійний номер апаратури пристрою і він унікальний. Отже, на рівні api 2.3 і вище ви можете використовувати android.os.Build.ANDROID_ID, щоб отримати його. Для рівня нижче 2.3 використовуйте TelephonyManager.getDeviceID () .

ви можете прочитати це http://android-developers.blogspot.in/2011/03/identifying-app-installations.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.