Czy urządzenia z Androidem mają unikalny identyfikator, a jeśli tak, to jaki jest prosty sposób na dostęp do niego za pomocą Java?
Czy urządzenia z Androidem mają unikalny identyfikator, a jeśli tak, to jaki jest prosty sposób na dostęp do niego za pomocą Java?
Odpowiedzi:
Settings.Secure#ANDROID_ID
zwraca identyfikator Androida jako unikalny dla każdego 64-bitowego ciągu szesnastkowego użytkownika.
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
AKTUALIZACJA : Od najnowszych wersji Androida wiele problemów ANDROID_ID
zostało rozwiązanych i uważam, że to podejście nie jest już konieczne. Proszę spojrzeć na odpowiedź Anthony'ego .
Pełne ujawnienie: moja aplikacja początkowo stosowała poniższe podejście, ale już nie stosuje tego podejścia, a teraz korzystamy z podejścia opisanego we wpisie na blogu programisty Androida, do którego prowadzi link odpowiedzi emmby (a mianowicie, generowanie i zapisywanie a UUID#randomUUID()
).
Istnieje wiele odpowiedzi na to pytanie, z których większość będzie działać tylko „przez pewien czas”, i niestety to nie wystarczy.
Na podstawie moich testów urządzeń (wszystkich telefonów, z których przynajmniej jeden nie jest aktywowany):
TelephonyManager.getDeviceId()
TelephonyManager.getSimSerialNumber()
getSimSerialNumber()
(zgodnie z oczekiwaniami)ANDROID_ID
ANDROID_ID
i TelephonyManager.getDeviceId()
- o ile konto Google zostało dodane podczas instalacji.Więc jeśli chcesz czegoś wyjątkowego dla samego urządzenia, TM.getDeviceId()
powinno wystarczyć. Oczywiście niektórzy użytkownicy są bardziej paranoiczni niż inni, więc może być użyteczne zaszyfrowanie 1 lub więcej takich identyfikatorów, tak aby ciąg znaków był praktycznie unikalny dla urządzenia, ale nie identyfikował wyraźnie rzeczywistego urządzenia użytkownika. Na przykład przy użyciu String.hashCode()
w połączeniu z 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();
może spowodować coś takiego jak: 00000000-54b3-e7c7-0000-000046bffd97
Działa dla mnie wystarczająco dobrze.
Jak Richard wspomina poniżej, nie zapominaj, że potrzebujesz pozwolenia na odczytanie TelephonyManager
właściwości, więc dodaj to do swojego manifestu:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
importuj biblioteki lib
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
do pliku manifestu. W przypadku przechowywania w bazie danych zwracany ciąg ma 36 znaków.
Po przeczytaniu każdego wpisu przepełnienia stosu dotyczącego tworzenia unikalnego identyfikatora, blogu programisty Google i dokumentacji Androida, wydaje mi się, że „Pseudo-identyfikator” jest najlepszą możliwą opcją.
Kod Psuedo:
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)
Dzięki @stansult za opublikowanie wszystkich naszych opcji (w tym pytaniu Przepełnienie stosu).
Adres e-mail użytkownika - oprogramowanie
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
lub<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
( Jak uzyskać główny adres e-mail urządzenia z systemem Android )Numer telefonu użytkownika - oprogramowanie
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
IMEI - sprzęt (tylko telefony, potrzebne android.permission.READ_PHONE_STATE
)
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Android ID - sprzęt (może być zerowy, może ulec zmianie po przywróceniu ustawień fabrycznych, może być zmieniony na zrootowanym urządzeniu)
Adres MAC sieci WLAN - sprzęt (wymaga android.permission.ACCESS_WIFI_STATE
)
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
Adres MAC Bluetooth - sprzęt (urządzenia z Bluetooth, wymagają android.permission.BLUETOOTH
)
<uses-permission android:name="android.permission.BLUETOOTH "/>
Pseudo-unikalny identyfikator - oprogramowanie (dla wszystkich urządzeń z Androidem)
Wiem, że nie ma żadnego „idealnego” sposobu uzyskania unikalnego identyfikatora bez użycia uprawnień; Czasami jednak naprawdę musimy tylko śledzić instalację urządzenia. Jeśli chodzi o tworzenie unikalnego identyfikatora, możemy stworzyć „pseudo unikalny identyfikator” oparty wyłącznie na informacjach, które daje nam interfejs API Androida, bez korzystania z dodatkowych uprawnień. W ten sposób możemy okazywać szacunek użytkownikom i starać się oferować dobre wrażenia.
Dzięki pseudo-unikalnemu identyfikatorowi tak naprawdę napotykasz tylko na fakt, że mogą istnieć duplikaty na podstawie faktu, że istnieją podobne urządzenia. Możesz dostosować połączoną metodę, aby była bardziej unikalna; Jednak niektórzy programiści muszą śledzić instalacje urządzeń, a to zrobi sztuczkę lub wydajność w oparciu o podobne urządzenia.
Jeśli ich urządzeniem z Androidem jest API 9 lub nowszy, gwarantuje to, że będzie unikalny ze względu na pole „Build.SERIAL”.
PAMIĘTAJ , że technicznie brakuje Ci tylko około 0,5% użytkowników, którzy mają API <9 . Możesz więc skupić się na reszcie: to 99,5% użytkowników!
Jeśli urządzenie z Androidem użytkownika jest niższe niż API 9; mam nadzieję, że nie przywrócono ustawień fabrycznych, a ich „Secure.ANDROID_ID” zostanie zachowany lub nie będzie „zerowy”. (patrz http://developer.android.com/about/dashboards/index.html )
Jeśli wszystko inne zawiedzie, jeśli użytkownik ma niższą niż API 9 (niższą niż Gingerbread), zresetował swoje urządzenie lub „Secure.ANDROID_ID” zwraca „null”, wówczas zwrócony identyfikator będzie wyłącznie oparty na informacjach o urządzeniu z Androidem. To tutaj mogą zdarzyć się kolizje.
Zmiany:
Proszę spojrzeć na poniższą metodę:
/**
* 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();
}
Z konsoli programisty Google Play:
Począwszy od 1 sierpnia 2014 r., Zasady programu dla programistów Google Play wymagają, aby wszystkie nowe aplikacje i aktualizacje aplikacji używały identyfikatora reklamowego zamiast innych trwałych identyfikatorów do jakichkolwiek celów reklamowych. Ucz się więcej
Realizacja :
Pozwolenie:
<uses-permission android:name="android.permission.INTERNET" />
Kod:
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();
}
Źródło / Dokumenty:
http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html
Zakłada się, że identyfikator reklamowy całkowicie zastąpi dotychczasowe użycie innych identyfikatorów do celów reklamowych (takich jak użycie ANDROID_ID w Settings.Secure), gdy Usługi Google Play są dostępne. Przypadki, w których Usługi Google Play są niedostępne, są wskazywane przez wyjątek GooglePlayServicesNotAvailableException przez getAdvertisingIdInfo ().
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
Próbowałem odwoływać się do każdego linku, z którego wziąłem informacje. Jeśli brakuje i trzeba je uwzględnić, prosimy o komentarz!
Build
klasa nie zmieni się po aktualizacji systemu operacyjnego? Zwłaszcza jeśli interfejs API został zaktualizowany? Jeśli tak, w jaki sposób gwarantujesz, że jest to wyjątkowe? (Mówiąc o metodzie, którą napisałeś)
Jak wspomina Dave Webb, blog programisty Androida zawiera artykuł na ten temat. Preferowanym przez nich rozwiązaniem jest śledzenie instalacji aplikacji, a nie urządzeń, i będzie to działać dobrze w większości przypadków użycia. Wpis na blogu zawiera kod niezbędny do tego, aby działał, i polecam go sprawdzić.
Jednak blog nadal omawia rozwiązania, jeśli potrzebujesz identyfikatora urządzenia zamiast identyfikatora instalacji aplikacji. Rozmawiałem z kimś z Google, aby uzyskać dodatkowe wyjaśnienia dotyczące kilku elementów na wypadek, gdybyś musiał to zrobić. Oto, co odkryłem na temat identyfikatorów urządzeń, o których NIE wspomniano w wyżej wspomnianym wpisie na blogu:
Opierając się na zaleceniach Google, zaimplementowałem klasę, która wygeneruje unikalny UUID dla każdego urządzenia, używając ANDROID_ID w razie potrzeby jako seed, w razie potrzeby odwołując się do TelephonyManager.getDeviceId (), a jeśli to się nie powiedzie, uciekając się do losowo generowanego unikalnego UUID jest to powtarzane po ponownym uruchomieniu aplikacji (ale nie ponownej instalacji aplikacji).
Należy pamiętać, że w przypadku urządzeń, które muszą mieć awarię identyfikatora urządzenia, unikatowy identyfikator BĘDZIE występował podczas resetowania do ustawień fabrycznych. Jest to coś, o czym należy pamiętać. Jeśli musisz upewnić się, że przywrócenie ustawień fabrycznych spowoduje zresetowanie unikalnego identyfikatora, możesz rozważyć powrót bezpośrednio do losowego identyfikatora UUID zamiast identyfikatora urządzenia.
Ponownie ten kod dotyczy identyfikatora urządzenia, a nie identyfikatora instalacji aplikacji. W większości sytuacji prawdopodobnie szukasz identyfikatora instalacji aplikacji. Ale jeśli potrzebujesz identyfikatora urządzenia, prawdopodobnie poniższy kod będzie dla Ciebie odpowiedni.
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;
}
}
Oto kod, którego Reto Meier użył w tegorocznej prezentacji Google I / O, aby uzyskać unikalny identyfikator dla użytkownika:
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;
}
Jeśli para to z kopii zapasowej strategii wysyłania preferencje w chmurze (także opisane w Reto w rozmowie , trzeba mieć identyfikator, który więzi z użytkownikiem i kije wokół po urządzenie zostało wymazane, a nawet wymienić. Mam zamiar to wykorzystać w analityce w przyszłości (innymi słowy, jeszcze tego nie zrobiłem :).
Możesz również wziąć pod uwagę adres MAC karty Wi-Fi. Pobrano w ten sposób:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Wymaga zgody android.permission.ACCESS_WIFI_STATE
w manifeście.
Zgłoszone jako dostępne, nawet gdy Wi-Fi nie jest podłączone. Jeśli Joe z powyższej odpowiedzi wypróbuje ten na wielu swoich urządzeniach, byłoby miło.
Na niektórych urządzeniach nie jest dostępny, gdy Wi-Fi jest wyłączone.
UWAGA: Z systemu Android 6.x zwraca spójny fałszywy adres mac:02:00:00:00:00:00
android.permission.ACCESS_WIFI_STATE
02:00:00:00:00:00
Jest raczej przydatna informacji tutaj .
Obejmuje pięć różnych typów identyfikatorów:
android.permission.READ_PHONE_STATE
)android.permission.ACCESS_WIFI_STATE
)android.permission.BLUETOOTH
)Oficjalny blog programistów Androida zawiera teraz pełny artykuł na ten temat - Identyfikowanie instalacji aplikacji .
W Google I / O Reto Meier opublikował solidną odpowiedź na pytanie, jak podejść do tego, co powinno zaspokoić większość programistów potrzebujących śledzić użytkowników w różnych instalacjach. Anthony Nolan wskazuje kierunek w swojej odpowiedzi, ale pomyślałem, że wypiszę pełne podejście, aby inni mogli łatwo zobaczyć, jak to zrobić (zajęło mi trochę czasu, aby zrozumieć szczegóły).
Takie podejście da ci anonimowy, bezpieczny identyfikator użytkownika, który będzie trwały dla użytkownika na różnych urządzeniach (w oparciu o podstawowe konto Google) i we wszystkich instalacjach. Podstawowym podejściem jest wygenerowanie losowego identyfikatora użytkownika i zapisanie go we wspólnych preferencjach aplikacji. Następnie używasz agenta kopii zapasowej Google do przechowywania wspólnych preferencji powiązanych z kontem Google w chmurze.
Przejdźmy przez pełne podejście. Najpierw musimy utworzyć kopię zapasową naszych wspólnych preferencji za pomocą usługi Android Backup Service. Zacznij od zarejestrowania aplikacji za pośrednictwem http://developer.android.com/google/backup/signup.html
.
Google da ci klucz usługi kopii zapasowej, który musisz dodać do manifestu. Musisz także powiedzieć aplikacji, aby korzystała z BackupAgent w następujący sposób:
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="your_backup_service_key" />
</application>
Następnie musisz utworzyć agenta kopii zapasowej i powiedzieć mu, aby używał agenta pomocniczego do wspólnych preferencji:
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);
}
}
Aby zakończyć tworzenie kopii zapasowej, musisz utworzyć instancję BackupManager w głównym działaniu:
BackupManager backupManager = new BackupManager(context);
Na koniec utwórz identyfikator użytkownika, jeśli jeszcze nie istnieje, i zapisz go w 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;
}
Ten identyfikator_użytkownika będzie teraz trwały w różnych instalacjach, nawet jeśli użytkownik przeniesie urządzenie.
Więcej informacji na temat tego podejścia można znaleźć w wykładzie Reto .
Aby uzyskać szczegółowe informacje na temat wdrażania agenta kopii zapasowej, zobacz Kopia zapasowa danych . Szczególnie polecam sekcję na dole dotyczącą testowania, ponieważ tworzenie kopii zapasowej nie następuje natychmiast, więc aby przetestować, musisz wymusić wykonanie kopii zapasowej.
Myślę, że to z pewnością ognisty sposób na zbudowanie szkieletu dla unikalnego ID ... sprawdź to.
Pseudo-unikalny identyfikator, który działa na wszystkich urządzeniach z Androidem Niektóre urządzenia nie mają telefonu (np. Tablety) lub z jakiegoś powodu nie chcesz dołączać uprawnienia READ_PHONE_STATE. Nadal możesz odczytać szczegóły, takie jak wersja ROM, nazwa producenta, typ procesora i inne szczegóły sprzętowe, które będą odpowiednie, jeśli chcesz użyć identyfikatora do sprawdzania klucza szeregowego lub do innych ogólnych celów. Obliczony w ten sposób identyfikator nie będzie unikalny: można znaleźć dwa urządzenia o tym samym identyfikatorze (oparte na tym samym sprzęcie i obrazie ROM), ale zmiany w rzeczywistych aplikacjach są nieistotne. W tym celu możesz użyć klasy 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
Większość członków Kompilacji to łańcuchy, a my tutaj zajmujemy ich długość i przekształcamy je za pomocą modulo w cyfrę. Mamy 13 takich cyfr i dodajemy dwie kolejne z przodu (35), aby mieć taki sam identyfikator rozmiaru jak IMEI (15 cyfr). Są tutaj inne możliwości, spójrz tylko na te struny. Zwraca coś takiego 355715565309247
. Nie jest wymagane specjalne pozwolenie, dzięki czemu takie podejście jest bardzo wygodne.
(Dodatkowe informacje: technika podana powyżej została skopiowana z artykułu o Pocket Magic .)
Poniższy kod zwraca numer seryjny urządzenia przy użyciu ukrytego interfejsu API Androida. Ale ten kod nie działa na Samsung Galaxy Tab, ponieważ „ro.serialno” nie jest ustawione na tym urządzeniu.
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) {
}
ro.serialno
jest on używany do generowania Settings.Secure.ANDROID_ID
. Są to w zasadzie różne reprezentacje o tej samej wartości.
ANDROID_ID
Z tego wynika tylko nowa wartość dla .
android.os.Build.SERIAL
android.os.Build.SERIAL
będzie przestarzałe w Androidzie O, patrz android-developers.googleblog.com/2017/04/…
To proste pytanie, bez prostej odpowiedzi.
Co więcej, wszystkie istniejące odpowiedzi tutaj są nieaktualne lub niewiarygodne.
Więc jeśli szukasz rozwiązania w 2020 roku .
Oto kilka rzeczy, o których należy pamiętać:
Wszystkie identyfikatory sprzętowe (SSAID, IMEI, MAC itp.) Są niewiarygodne w przypadku urządzeń innych niż Google (wszystko oprócz pikseli i nexusów), które stanowią ponad 50% aktywnych urządzeń na całym świecie. Dlatego oficjalne najlepsze praktyki dotyczące identyfikatorów Androida wyraźnie stwierdzają:
Unikaj używania identyfikatorów sprzętowych , takich jak SSAID (Android ID), IMEI, adres MAC itp.
To sprawia, że większość powyższych odpowiedzi jest nieważna. Również z powodu różnych aktualizacji zabezpieczeń Androida niektóre z nich wymagają nowszych i bardziej rygorystycznych uprawnień do wykonywania, których użytkownik może po prostu odmówić.
Jako przykład, CVE-2018-9489
który wpływa na wszystkie wyżej wymienione techniki oparte na WIFI.
To sprawia, że te identyfikatory są nie tylko zawodne, ale również niedostępne w wielu przypadkach.
Mówiąc prościej: nie używaj tych technik .
Wiele innych odpowiedzi tutaj sugeruje użycie AdvertisingIdClient
, który jest również niezgodny, ponieważ z założenia należy go używać tylko do profilowania reklam. Jest to również określone w oficjalnym odnośniku
Używaj identyfikatora reklamowego tylko do profilowania użytkowników lub przypadków użycia reklam
Identyfikacja urządzenia jest nie tylko niewiarygodna, ale należy również przestrzegać zasad prywatności użytkownika dotyczących zasad śledzenia reklam , które wyraźnie stwierdzają, że użytkownik może je zresetować lub zablokować w dowolnym momencie.
Więc też go nie używaj .
Ponieważ nie można mieć żądanego statycznego, unikalnego globalnie i niezawodnego identyfikatora urządzenia. Oficjalne referencje Androida sugerują:
Używaj FirebaseInstanceId lub prywatnego GUID, o ile to możliwe, we wszystkich innych przypadkach użycia, z wyjątkiem zapobiegania oszustwom płatniczym i telefonii.
Jest unikalny w przypadku instalacji aplikacji na urządzeniu, więc gdy użytkownik odinstaluje aplikację - jest usuwana, więc nie jest w 100% niezawodna, ale jest następną najlepszą rzeczą.
Aby użyć, FirebaseInstanceId
dodaj najnowszą zależność Firebase -Messaging do swojej oceny
implementation 'com.google.firebase:firebase-messaging:20.2.0'
I użyj poniższego kodu w wątku w tle:
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
Jeśli musisz zapisać identyfikator urządzenia na zdalnym serwerze, nie przechowuj go takim, jaki jest (zwykły tekst), ale skrót z solą .
Dzisiaj jest to nie tylko najlepsza praktyka, ale musisz to zrobić zgodnie z prawem zgodnie z RODO - identyfikatory i podobne regulacje.
Korzystając z poniższego kodu, możesz uzyskać unikatowy identyfikator urządzenia z systemem Android jako ciąg.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Seryjny pole dodano do Build
klasy poziomu API 9 (Mobile 2.3 - pierniki). Dokumentacja mówi, że reprezentuje numer seryjny sprzętu. Dlatego powinien być unikalny, jeśli istnieje na urządzeniu.
Nie wiem jednak, czy jest on faktycznie obsługiwany (= nie zerowy) przez wszystkie urządzenia z poziomem API> = 9.
Dodam jeszcze jedną rzecz - mam jedną z tych wyjątkowych sytuacji.
Za pomocą:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
Okazuje się, że chociaż mój tablet Viewsonic G zgłasza identyfikator urządzenia, który nie ma wartości NULL, każdy tablet G ma ten sam numer.
Sprawia, że gra w „Pocket Empires” staje się interesująca, co zapewnia natychmiastowy dostęp do czyjegoś konta na podstawie „unikalnego” DeviceID.
Moje urządzenie nie ma radia komórkowego.
9774d56d682e549c
?
Szczegółowe instrukcje na temat uzyskiwania unikalnego identyfikatora dla każdego urządzenia z Androidem, z którego zainstalowana jest aplikacja, można znaleźć na oficjalnym blogu programistów Androida, w którym opisano instalacje aplikacji .
Wydaje się, że najlepszym sposobem jest wygenerowanie go samodzielnie podczas instalacji, a następnie przeczytanie go po ponownym uruchomieniu aplikacji.
Osobiście uważam to za dopuszczalne, ale nie idealne. Żaden identyfikator podany przez Androida nie działa we wszystkich przypadkach, ponieważ większość zależy od stanu radia telefonu (Wi-Fi wł. / Wył., Wł. / Wył. Komórkowy, wł. / Wył. Bluetooth). Inne, podobnie jak Settings.Secure.ANDROID_ID
muszą być wdrożone przez producenta i nie ma gwarancji, że będą unikalne.
Poniżej znajduje się przykład zapisu danych do pliku instalacyjnego , który byłby przechowywany wraz z wszelkimi innymi danymi zapisywanymi lokalnie przez aplikację.
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();
}
}
Dodaj poniższy kod w pliku klasy:
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);
Dodaj w AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
TelephonyManager
i ANDROID_ID
, jest uzyskiwany przez: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);
}
Ale zdecydowanie zalecam metodę sugerowaną przez Google, patrz Identyfikacja instalacji aplikacji .
Istnieje wiele różnych podejść do obejścia tych ANDROID_ID
problemów (mogą być null
czasami lub urządzenia określonego modelu zawsze zwracają ten sam identyfikator) z zaletami i wadami:
Sam wolę używać istniejącej implementacji OpenUDID (patrz https://github.com/ylechelle/OpenUDID ) dla Androida (patrz https://github.com/vieux/OpenUDID ). Jest łatwa do zintegrowania i wykorzystuje ANDROID_ID
awarie w przypadku wyżej wymienionych problemów.
Co powiesz na IMEI . Jest to unikalne rozwiązanie dla Androida lub innych urządzeń mobilnych.
Oto jak generuję unikalny identyfikator:
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;
}
Moje dwa centy - NB, to jest za unikatowy identyfikator urządzenia - nie ten instalacyjny, jak omówiono na blogu programistów Androida .
Należy zauważyć, że rozwiązanie dostarczone przez @emmby ma identyfikator ID aplikacji, ponieważ SharedPreferences nie są synchronizowane między procesami (patrz tutaj i tutaj ). Więc całkowicie tego uniknąłem.
Zamiast tego hermetyzowałem różne strategie uzyskiwania identyfikatora (urządzenia) w wyliczeniu - zmiana kolejności stałych wyliczania wpływa na priorytet różnych sposobów uzyskiwania identyfikatora. Zwracany jest pierwszy niepusty identyfikator lub generowany jest wyjątek (zgodnie z dobrymi praktykami Java, aby nie nadawać null znaczenia). Na przykład mam najpierw TELEPHONY - ale dobrym wyborem domyślnym byłaby wersja ANDROID_ID beta:
import android.Manifest.permission;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.util.Log;
// TODO : hash
public final class DeviceIdentifier {
private DeviceIdentifier() {}
/** @see http://code.google.com/p/android/issues/detail?id=10603 */
private static final String ANDROID_ID_BUG_MSG = "The device suffers from "
+ "the Android ID bug - its ID is the emulator ID : "
+ IDs.BUGGY_ANDROID_ID;
private static volatile String uuid; // volatile needed - see EJ item 71
// need lazy initialization to get a context
/**
* Returns a unique identifier for this device. The first (in the order the
* enums constants as defined in the IDs enum) non null identifier is
* returned or a DeviceIDException is thrown. A DeviceIDException is also
* thrown if ignoreBuggyAndroidID is false and the device has the Android ID
* bug
*
* @param ctx
* an Android constant (to retrieve system services)
* @param ignoreBuggyAndroidID
* if false, on a device with the android ID bug, the buggy
* android ID is not returned instead a DeviceIDException is
* thrown
* @return a *device* ID - null is never returned, instead a
* DeviceIDException is thrown
* @throws DeviceIDException
* if none of the enum methods manages to return a device ID
*/
public static String getDeviceIdentifier(Context ctx,
boolean ignoreBuggyAndroidID) throws DeviceIDException {
String result = uuid;
if (result == null) {
synchronized (DeviceIdentifier.class) {
result = uuid;
if (result == null) {
for (IDs id : IDs.values()) {
try {
result = uuid = id.getId(ctx);
} catch (DeviceIDNotUniqueException e) {
if (!ignoreBuggyAndroidID)
throw new DeviceIDException(e);
}
if (result != null) return result;
}
throw new DeviceIDException();
}
}
}
return result;
}
private static enum IDs {
TELEPHONY_ID {
@Override
String getId(Context ctx) {
// TODO : add a SIM based mechanism ? tm.getSimSerialNumber();
final TelephonyManager tm = (TelephonyManager) ctx
.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
w("Telephony Manager not available");
return null;
}
assertPermission(ctx, permission.READ_PHONE_STATE);
return tm.getDeviceId();
}
},
ANDROID_ID {
@Override
String getId(Context ctx) throws DeviceIDException {
// no permission needed !
final String andoidId = Secure.getString(
ctx.getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID);
if (BUGGY_ANDROID_ID.equals(andoidId)) {
e(ANDROID_ID_BUG_MSG);
throw new DeviceIDNotUniqueException();
}
return andoidId;
}
},
WIFI_MAC {
@Override
String getId(Context ctx) {
WifiManager wm = (WifiManager) ctx
.getSystemService(Context.WIFI_SERVICE);
if (wm == null) {
w("Wifi Manager not available");
return null;
}
assertPermission(ctx, permission.ACCESS_WIFI_STATE); // I guess
// getMacAddress() has no java doc !!!
return wm.getConnectionInfo().getMacAddress();
}
},
BLUETOOTH_MAC {
@Override
String getId(Context ctx) {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
w("Bluetooth Adapter not available");
return null;
}
assertPermission(ctx, permission.BLUETOOTH);
return ba.getAddress();
}
}
// TODO PSEUDO_ID
// http://www.pocketmagic.net/2011/02/android-unique-device-id/
;
static final String BUGGY_ANDROID_ID = "9774d56d682e549c";
private final static String TAG = IDs.class.getSimpleName();
abstract String getId(Context ctx) throws DeviceIDException;
private static void w(String msg) {
Log.w(TAG, msg);
}
private static void e(String msg) {
Log.e(TAG, msg);
}
}
private static void assertPermission(Context ctx, String perm) {
final int checkPermission = ctx.getPackageManager().checkPermission(
perm, ctx.getPackageName());
if (checkPermission != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Permission " + perm + " is required");
}
}
// =========================================================================
// Exceptions
// =========================================================================
public static class DeviceIDException extends Exception {
private static final long serialVersionUID = -8083699995384519417L;
private static final String NO_ANDROID_ID = "Could not retrieve a "
+ "device ID";
public DeviceIDException(Throwable throwable) {
super(NO_ANDROID_ID, throwable);
}
public DeviceIDException(String detailMessage) {
super(detailMessage);
}
public DeviceIDException() {
super(NO_ANDROID_ID);
}
}
public static final class DeviceIDNotUniqueException extends
DeviceIDException {
private static final long serialVersionUID = -8940090896069484955L;
public DeviceIDNotUniqueException() {
super(ANDROID_ID_BUG_MSG);
}
}
}
Tutaj jest ponad 30 odpowiedzi, a niektóre są takie same, a niektóre są wyjątkowe. Ta odpowiedź jest oparta na kilku z tych odpowiedzi. Jednym z nich jest odpowiedź @Lenn Dolling.
Łączy 3 identyfikatory i tworzy 32-cyfrowy ciąg szesnastkowy. To działało dla mnie bardzo dobrze.
3 identyfikatory to:
Pseudo-identyfikator - jest generowany na podstawie fizycznych specyfikacji urządzenia
ANDROID_ID - Settings.Secure.ANDROID_ID
adres Bluetooth - adres adaptera Bluetooth
Zwróci coś takiego: 551F27C060712A72730B0A0F734064B1
Uwaga: Zawsze możesz dodać więcej identyfikatorów do longId
łańcucha. Na przykład numer seryjny. adres adaptera wifi. IMEI. W ten sposób czynisz go bardziej unikalnym dla każdego urządzenia.
@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 "";
}
longId
pliku i zapisanie go w pliku sprawi, że będzie on najbardziej unikalnym identyfikatorem:String uuid = UUID.randomUUID().toString();
longId
. Zmień tę jedną linię w ten sposób: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString();
Gwarantuje to, że wygenerowany identyfikator będzie unikalny.
Innym sposobem jest korzystanie /sys/class/android_usb/android0/iSerial
z aplikacji bez żadnych uprawnień.
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
Aby to zrobić w Javie, wystarczy użyć FileInputStream, aby otworzyć plik iSerial i odczytać znaki. Tylko upewnij się, że umieścisz go w module obsługi wyjątków, ponieważ nie wszystkie urządzenia mają ten plik.
Wiadomo, że przynajmniej następujące urządzenia mają ten plik do odczytu na całym świecie:
Możesz także zobaczyć mój wpis na blogu Wyciekający numer seryjny sprzętu Android do nieuprzywilejowanych aplikacji, w którym omawiam, jakie inne pliki są dostępne do informacji.
TelephonyManger.getDeviceId () Zwraca unikalny identyfikator urządzenia, na przykład IMEI dla GSM i MEID lub ESN dla telefonów CDMA.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
Ale polecam użyć:
Settings.Secure.ANDROID_ID, który zwraca identyfikator Androida jako unikalny 64-bitowy ciąg szesnastkowy.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Czasami TelephonyManger.getDeviceId () zwraca null, więc aby zapewnić unikalny identyfikator, użyjesz tej metody:
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;
}
Aby rozpoznać sprzętowo określone urządzenie z Androidem, możesz sprawdzić adresy MAC.
możesz to zrobić w ten sposób:
w AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
teraz w kodzie:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
Na każdym urządzeniu z Androidem ich interfejs jest co najmniej „wlan0”, a układ WI-FI. Ten kod działa nawet wtedy, gdy WI-FI nie jest włączony.
PS Ich jest wiele innych interfejsów, które otrzymasz z listy zawierającej MACS Ale to może się zmieniać między telefonami.
Używam następującego kodu, aby uzyskać IMEI
lub użyć Bezpieczne. ANDROID_ID
alternatywnie, gdy urządzenie nie ma możliwości telefonu:
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);
Dokładniej Settings.Secure.ANDROID_ID
. Jest to 64-bitowa ilość, która jest generowana i przechowywana przy pierwszym uruchomieniu urządzenia. Jest resetowany po wyczyszczeniu urządzenia.
ANDROID_ID
wydaje się dobrym wyborem dla unikalnego identyfikatora urządzenia. Są wady: Po pierwsze, nie jest w 100% wiarygodny w wersjach Androida wcześniejszych niż 2.2. (“Froyo”).
Ponadto w popularnym telefonie od jednego z głównych producentów pojawił się co najmniej jeden powszechnie obserwowany błąd, w którym każda instancja ma ten sam ANDROID_ID.
Aby zrozumieć dostępne unikalne identyfikatory na urządzeniach z Androidem. Skorzystaj z tego oficjalnego przewodnika.
Najlepsze praktyki dotyczące unikalnych identyfikatorów:
IMEI, adresy Mac, identyfikator wystąpienia, identyfikatory GUID, identyfikator SSAID, identyfikator reklamowy, interfejs API sieci bezpieczeństwa do weryfikacji urządzeń.
https://developer.android.com/training/articles/user-data-ids
Identyfikator wystąpienia Google
Wydany na I / O 2015; na Androida wymaga usług Play 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
Wygląda na to, że Google zamierza użyć tego identyfikatora do identyfikacji instalacji na Androidzie, Chrome i iOS.
Identyfikuje instalację, a nie urządzenie, ale z drugiej strony ANDROID_ID (który jest akceptowaną odpowiedzią) nie rozpoznaje już urządzeń. W środowisku wykonawczym ARC generowany jest nowy ANDROID_ID dla każdej instalacji ( szczegóły tutaj ), podobnie jak ten nowy identyfikator instancji. Myślę też, że identyfikacja instalacji (a nie urządzeń) jest tym, czego tak naprawdę szuka większość z nas.
Zalety identyfikatora instancji
Wydaje mi się, że Google zamierza używać go w tym celu (identyfikując twoje instalacje), jest wieloplatformowy i może być wykorzystywany do wielu innych celów (patrz linki powyżej).
Jeśli używasz GCM, w końcu będziesz musiał użyć tego identyfikatora instancji, ponieważ jest on potrzebny, aby uzyskać token GCM (który zastępuje stary identyfikator rejestracji GCM).
Wady / problemy
W bieżącej implementacji (GPS 7.5) identyfikator instancji jest pobierany z serwera na żądanie aplikacji. Oznacza to, że powyższe połączenie jest połączeniem blokującym - w moich testach nienaukowych zajmuje 1-3 sekund, jeśli urządzenie jest w trybie online, i 0,5 - 1,0 sekundy, jeśli jest w trybie off-line (przypuszczalnie tyle czasu czeka przed rezygnacją i wygenerowaniem losowy identyfikator). Zostało to przetestowane w Ameryce Północnej na Nexusie 5 z Androidem 5.1.1 i GPS 7.5.
Jeśli używasz identyfikatora do celów, które zamierzają - np. uwierzytelnianie aplikacji, identyfikacja aplikacji, GCM - Myślę, że 1-3 sekundy mogą być uciążliwe (oczywiście w zależności od aplikacji).
ANDROID_ID
, przeczytaj tę odpowiedź i ten błąd .