Существует ли уникальный идентификатор устройства Android? - PullRequest
2562 голосов
/ 07 мая 2010

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

Ответы [ 43 ]

4 голосов
/ 02 ноября 2013

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

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

и

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

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

Подробнее @ develper.android

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

НТН

3 голосов
/ 04 мая 2019

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

Лучшие практики для уникальных идентификаторов:

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

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

3 голосов
/ 28 декабря 2017

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

@SuppressLint("HardwareIds")
private String getDeviceID() {
    deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(),
                    Settings.Secure.ANDROID_ID);
    return deviceId;
}
2 голосов
/ 11 июня 2019

Вот простой ответ, чтобы получить 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();

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

2 голосов
/ 07 ноября 2017

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

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

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

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;
} 
1 голос
/ 11 апреля 2017

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

https://android -developers.googleblog.com / 2017/04 / изменения к устройству-идентификаторы-in.html

tl; dr Serial потребуется разрешение PHONE, а идентификатор Android изменится для разных приложений в зависимости от имени пакета и подписи.

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

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

1 голос
/ 31 января 2019

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

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

1 голос
/ 19 июня 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;
}
1 голос
/ 14 декабря 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;
}

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

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

1 голос
/ 07 сентября 2017
String SERIAL_NUMER = Build.SERIAL;

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...