Dispozitivele Android au un ID unic și, dacă da, care este o modalitate simplă de a-l accesa folosind Java?
Există un ID unic de dispozitiv Android?
Răspunsuri (50)
Settings.Secure#ANDROID_ID returnează ID-ul Android ca unic pentru fiecare utilizator hexadecimal pe 64 de biți şir.
import android.provider.Settings.Secure;
private String android_id = Secure.getString(getContext().getContentResolver(),
Secure.ANDROID_ID);
Citiți și Cele mai bune practici pentru identificatorii unici: https://developer.android.com/training/articles/user-data-ids
ANDROID_ID - nu pot replica asta în testare, totuși - merită să fie conștient oricum...
- person Dori; 06.03.2014
ACTUALIZARE: începând cu versiunile recente de Android, multe dintre problemele legate de ANDROID_ID au fost rezolvate și cred că această abordare nu mai este necesară. Vă rugăm să aruncați o privire la răspunsul lui Anthony.
Dezvăluire completă: aplicația mea a folosit abordarea de mai jos inițial, dar nu mai folosește această abordare, iar acum folosim abordarea prezentată în Blog pentru dezvoltatori Android intrare la care răspunsul lui Emmby trimite (și anume , generând și salvând un UUID#randomUUID()).
Există multe răspunsuri la această întrebare, dintre care cele mai multe vor funcționa doar o parte din timp și, din păcate, asta nu este suficient de bun.
Pe baza testelor mele de dispozitive (toate telefoanele, dintre care cel puțin unul nu este activat):
- Toate dispozitivele testate au returnat o valoare pentru
TelephonyManager.getDeviceId() - Toate dispozitivele GSM (toate testate cu un SIM) au returnat o valoare pentru
TelephonyManager.getSimSerialNumber() - Toate dispozitivele CDMA au returnat nul pentru
getSimSerialNumber()(după cum era de așteptat) - Toate dispozitivele cu un cont Google adăugat au returnat o valoare pentru
ANDROID_ID - Toate dispozitivele CDMA au returnat aceeași valoare (sau derivarea aceleiași valori) atât pentru
ANDROID_ID, cât și pentruTelephonyManager.getDeviceId()-- atâta timp cât a fost adăugat un cont Google în timpul configurării. - Nu am avut încă șansa de a testa dispozitive GSM fără SIM, un dispozitiv GSM fără cont Google adăugat sau oricare dintre dispozitivele în modul avion.
Deci, dacă doriți ceva unic pentru dispozitivul în sine, TM.getDeviceId() ar trebui să fie suficient. În mod evident, unii utilizatori sunt mai paranoici decât alții, așa că ar putea fi util să trimiți 1 sau mai mulți dintre acești identificatori, astfel încât șirul să fie practic unic pentru dispozitiv, dar să nu identifice în mod explicit dispozitivul real al utilizatorului. De exemplu, folosind String.hashCode(), combinat cu un 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();
ar putea avea ca rezultat ceva de genul: 00000000-54b3-e7c7-0000-000046bffd97
Funcționează suficient de bine pentru mine.
După cum menționează Richard mai jos, nu uitați că aveți nevoie de permisiunea pentru a citi proprietățile TelephonyManager, așa că adăugați asta în manifest:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
importa biblioteci
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> la fișierul manifest. Dacă se stochează într-o bază de date, șirul returnat are 36 de caractere.
- person Richard; 28.02.2011
#Ultima actualizare: 6/2/15
După ce am citit fiecare postare Stack Overflow despre crearea unui ID unic, blogul dezvoltatorului Google și documentația Android, simt că „Pseudo ID” este cea mai bună opțiune posibilă.
Problemă principală: Hardware vs Software
Hardware
- Utilizatorii își pot schimba hardware-ul, tableta Android sau telefonul, astfel încât ID-urile unice bazate pe hardware nu sunt idei bune pentru URMĂRIREA UTILIZATORULUI
- Pentru TRACKING HARDWARE, aceasta este o idee grozavă
Software
- Utilizatorii își pot șterge/schimba ROM-ul dacă sunt rootați
- Puteți urmări utilizatorii pe platforme (iOS, Android, Windows și Web)
- Cea mai bună dorință de a URMĂRIȚI UN UTILIZATOR INDIVIDUAL cu consimțământul acestuia este pur și simplu să-l autentificați (faceți acest lucru fără probleme folosind OAuth)
#Defalcare generală cu Android
###- Garantați unicitatea (includeți dispozitivele rootate) pentru API ›= 9/10 (99,5% dintre dispozitivele Android) ###- Fără permisiuni suplimentare
Cod pseudo:
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)
Mulțumim lui @stansult pentru postarea toate opțiunile noastre (în această întrebare Stack Overflow).
##Lista de opțiuni - motive pentru care/ de ce să nu le folosiți:
E-mail utilizator - Software
Utilizatorul ar putea schimba adresa de e-mail - FOARTE puțin probabil
API 5+
<uses-permission android:name="android.permission.GET_ACCOUNTS" />sauAPI 14+
<uses-permission android:name="android.permission.READ_PROFILE" /><uses-permission android:name="android.permission.READ_CONTACTS" />(Cum să obțineți dispozitivul Android adresa de e-mail principală)Numărul de telefon al utilizatorului - Software
Utilizatorii ar putea schimba numerele de telefon - FOARTE puțin probabil
<uses-permission android:name="android.permission.READ_PHONE_STATE" />IMEI - Hardware (numai telefoane, necesită
android.permission.READ_PHONE_STATE)Majoritatea utilizatorilor urăsc faptul că scrie Apeluri telefonice în permisiune. Unii utilizatori acordă evaluări proaste deoarece cred că pur și simplu le furați informațiile personale atunci când tot ceea ce doriți să faceți este să urmăriți instalările dispozitivului. Este evident că colectați date.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />ID Android - Hardware (poate fi nul, se poate modifica la resetarea din fabrică, poate fi modificat pe un dispozitiv rootat)
Deoarece poate fi „null”, putem verifica „null” și îi putem modifica valoarea, dar asta înseamnă că nu va mai fi unic.
Dacă aveți un utilizator cu un dispozitiv de resetare din fabrică, este posibil ca valoarea să se fi schimbat sau modificată pe dispozitivul înrădăcinat, astfel încât pot exista intrări duplicate dacă urmăriți instalările utilizatorilor.
Adresă MAC WLAN - Hardware (necesită
android.permission.ACCESS_WIFI_STATE)Aceasta ar putea fi a doua cea mai bună opțiune, dar încă colectați și stocați un identificator unic care vine direct de la un utilizator. Acest lucru este evident că colectați date.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>Adresă MAC Bluetooth - Hardware (dispozitive cu Bluetooth, necesită
android.permission.BLUETOOTH)Majoritatea aplicațiilor de pe piață nu folosesc Bluetooth și, prin urmare, dacă aplicația dvs. nu folosește Bluetooth și îl includeți, utilizatorul ar putea deveni suspicios.
<uses-permission android:name="android.permission.BLUETOOTH "/>ID pseudo-unic - Software (pentru toate dispozitivele Android)
Foarte posibil, poate conține coliziuni - Vezi metoda mea postată mai jos!
Acest lucru vă permite să aveți un ID „aproape unic” de la utilizator fără a lua nimic privat. Vă puteți crea propriul ID anonim din informațiile despre dispozitiv.
Știu că nu există nicio modalitate „perfectă” de a obține un ID unic fără a utiliza permisiunile; cu toate acestea, uneori trebuie doar să urmărim instalarea dispozitivului. Când vine vorba de crearea unui ID unic, putem crea un „pseudoid unic” bazat exclusiv pe informațiile pe care ni le oferă API-ul Android fără a folosi permisiuni suplimentare. În acest fel, putem arăta utilizatorului respect și putem încerca să oferim și o experiență bună pentru utilizator.
Cu un id pseudo-unic, într-adevăr te întâlnești doar cu faptul că pot exista duplicate pe baza faptului că există dispozitive similare. Puteți modifica metoda combinată pentru a o face mai unică; cu toate acestea, unii dezvoltatori trebuie să urmărească instalările dispozitivelor și acest lucru va face truc sau performanța pe baza dispozitivelor similare.
##API ›= 9:
Dacă dispozitivul lor Android are API 9 sau o versiune ulterioară, acesta este garantat a fi unic datorită câmpului „Build.SERIAL”.
ȚINE minte, din punct de vedere tehnic, pierdeți doar aproximativ 0,5% dintre utilizatorii care au API ‹ 9. Deci, vă puteți concentra pe restul: acesta este 99,5% dintre utilizatori!
##API ‹ 9:
Dacă dispozitivul Android al utilizatorului este mai mic decât API 9; sperăm că nu au făcut o resetare din fabrică și „Secure.ANDROID_ID” lor va fi păstrat sau nu „null”. (consultați http://developer.android.com/about/dashboards/index.html)
##Dacă toate celelalte nu reușesc:
Dacă toate celelalte eșuează, dacă utilizatorul are o versiune mai mică decât API 9 (mai mică decât Gingerbread), și-a resetat dispozitivul sau „Secure.ANDROID_ID” returnează „null”, atunci pur și simplu ID-ul returnat se va baza exclusiv pe informațiile dispozitivului său Android . Aici se pot produce ciocnirile.
Schimbări:
- S-a eliminat „Android.SECURE_ID” deoarece resetările din fabrică ar putea determina modificarea valorii
- Am editat codul pentru a fi modificat pe API
- Schimbat pseudo-ul
Vă rugăm să aruncați o privire la metoda de mai jos:
/**
* 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();
}
#Nou (pentru aplicații cu reclame ȘI Servicii Google Play):
Din consola pentru dezvoltatori Google Play:
Începând cu 1 august 2014, Politica de program pentru dezvoltatori Google Play necesită încărcări și actualizări de aplicații complet noi pentru a utiliza ID-ul de publicitate în locul oricăror alți identificatori persistenti în orice scop publicitar. Află mai multe
Implementare:
Permisiune:
<uses-permission android:name="android.permission.INTERNET" />
Cod:
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();
}
Sursă/Documente:
http://developer.android.com/google/play-services/id.html http://developer.android.com/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient.html
##Important:
Se intenționează ca ID-ul de publicitate să înlocuiască complet utilizarea existentă a altor identificatori în scopuri publicitare (cum ar fi utilizarea ANDROID_ID în Setări.Securizat) atunci când Serviciile Google Play sunt disponibile. Cazurile în care Serviciile Google Play sunt indisponibile sunt indicate de o excepție GooglePlayServicesNotAvailableException generată de getAdvertisingIdInfo().
##Atenție, utilizatorii pot reseta:
http://en.kioskea.net/faq/34732-android-reset-your-advertising-id
Am încercat să fac referire la fiecare link de la care am preluat informații. Dacă lipsești și trebuie să fii inclus, te rog să comentezi!
ID de instanță Google Player Services
https://developers.google.com/instance-id/
După cum menționează Dave Webb, Blogul dezvoltatorilor Android are un articol care acoperă asta. Soluția lor preferată este să urmărească instalările aplicațiilor, mai degrabă decât dispozitivele, iar asta va funcționa bine pentru majoritatea cazurilor de utilizare. Postarea de pe blog vă va arăta codul necesar pentru ca acest lucru să funcționeze și vă recomand să-l verificați.
Cu toate acestea, postarea de blog continuă să discute soluții dacă aveți nevoie de un identificator de dispozitiv, mai degrabă decât de un identificator de instalare a aplicației. Am vorbit cu cineva de la Google pentru a obține niște clarificări suplimentare cu privire la câteva elemente în cazul în care trebuie să faceți acest lucru. Iată ce am descoperit despre identificatorii de dispozitiv care NU sunt menționate în postarea de blog menționată mai sus:
- ANDROID_ID este identificatorul preferat de dispozitiv. ANDROID_ID este perfect de încredere pe versiunile de Android ‹=2.1 sau >=2.3. Doar 2.2 are problemele menționate în postare.
- Mai multe dispozitive de la mai mulți producători sunt afectate de eroarea ANDROID_ID din 2.2.
- Din câte am putut stabili, toate dispozitivele afectate au același ANDROID_ID, care este 9774d56d682e549c. Care este, de asemenea, același ID de dispozitiv raportat de emulator, btw.
- Google crede că OEM-urile au corectat problema pentru multe sau majoritatea dispozitivelor lor, dar am putut verifica că, cel puțin, de la începutul lui aprilie 2011, este încă destul de ușor să găsești dispozitive care au ANDROID_ID-ul stricat.
Pe baza recomandărilor Google, am implementat o clasă care va genera un UUID unic pentru fiecare dispozitiv, folosind ANDROID_ID ca seed acolo unde este cazul, recurgând înapoi la TelephonyManager.getDeviceId() după cum este necesar și, dacă nu reușește, recurgând la un UUID unic generat aleatoriu. care persistă la repornirile aplicației (dar nu la reinstalările aplicației).
Rețineți că, pentru dispozitivele care trebuie să recurgă la ID-ul dispozitivului, ID-ul unic VA persista la resetările din fabrică. Acesta este ceva de care trebuie să fii conștient. Dacă trebuie să vă asigurați că o resetare din fabrică vă va reseta ID-ul unic, poate doriți să luați în considerare revenirea direct la UUID-ul aleatoriu în loc de ID-ul dispozitivului.
Din nou, acest cod este pentru un ID de dispozitiv, nu pentru un ID de instalare a aplicației. Pentru majoritatea situațiilor, un ID de instalare a aplicației este probabil ceea ce cauți. Dar dacă aveți nevoie de un ID de dispozitiv, atunci următorul cod va funcționa probabil pentru dvs.
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;
}
}
Iată codul pe care Reto Meier l-a folosit în prezentarea Google I/O anul acesta pentru a obține un ID unic pentru utilizator:
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;
}
Dacă combinați acest lucru cu o strategie de rezervă pentru a trimite preferințe în cloud (descris și în discuți, ar trebui să ai un ID care se leagă de un utilizator și care rămâne după ce dispozitivul a fost șters sau chiar înlocuit. Intenționez să folosesc acest lucru în analiză mergând înainte (cu alte cuvinte, încă nu am făcut acel pic :).
De asemenea, ați putea lua în considerare adresa MAC a adaptorului Wi-Fi. Preluat astfel:
WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();
Necesită permisiunea android.permission.ACCESS_WIFI_STATE în manifest.
Raportat a fi disponibil chiar și atunci când Wi-Fi nu este conectat. Dacă Joe din răspunsul de mai sus îl încearcă pe acesta pe numeroasele sale dispozitive, ar fi bine.
Pe unele dispozitive, acesta nu este disponibil când Wi-Fi este dezactivat.
NOTĂ: de la Android 6.x, returnează o adresă Mac falsă consecventă: 02:00:00:00:00:00
Problema este că XML-ul tău folosește spațiul de nume implicit, dar XSD specifică un spațiu de nume țintă. Dacă specificați <BadManifest xmlns="http://www.engagesoftware.com/Schemas/EngageManifest"> în XML, ar trebui să descoperiți că validatorul raportează erori așa cum era de așteptat. În caz contrar, deoarece nu recunoaște spațiul de nume al XML-ului, pur și simplu îl ignoră.
02:00:00:00:00:00
- person Behrouz.M; 10.07.2016
Există informații destul de utile aici.
Acesta acoperă cinci tipuri de ID diferite:
- IMEI (numai pentru dispozitivele Android cu utilizarea telefonului; necesită
android.permission.READ_PHONE_STATE) - ID pseudo-unic (pentru toate dispozitivele Android)
- ID Android (poate fi nul, se poate modifica la resetarea din fabrică, poate fi modificat pe telefonul rootat)
- șir Adresă MAC WLAN (necesită
android.permission.ACCESS_WIFI_STATE) - Șir de adresă MAC BT (dispozitive cu Bluetooth, necesită
android.permission.BLUETOOTH)
Este o întrebare simplă, fără un răspuns simplu.
Mai mult, toate răspunsurile existente aici sunt învechite sau nesigure.
Deci, dacă sunteți în căutarea unei soluții în 2020.
Iată câteva lucruri de luat în considerare:
Toți identificatorii bazați pe hardware (SSAID, IMEI, MAC etc.) nu sunt de încredere pentru dispozitivele non-google (Totul, cu excepția Pixels și Nexus), care reprezintă mai mult de 50% dintre dispozitivele active din întreaga lume. Prin urmare, cele mai bune practici oficiale privind identificatorii Android precizează clar:
Evitați să utilizați identificatori hardware, cum ar fi SSAID (ID Android), IMEI, adresa MAC etc...
Asta face ca majoritatea răspunsurilor de mai sus să fie invalide. De asemenea, datorită diferitelor actualizări de securitate Android, unele dintre ele necesită permisiuni de rulare mai noi și mai stricte, care pot fi pur și simplu refuzate de utilizator.
Ca exemplu CVE-2018-9489 care afectează toate tehnicile bazate pe WIFI menționate mai sus.
Acest lucru face ca acești identificatori nu numai să fie nesiguri, ci și inaccesibili în multe cazuri.
Deci, cu cuvinte mai simple: nu folosi aceste tehnici.
Multe alte răspunsuri de aici sugerează să utilizați AdvertisingIdClient, care este, de asemenea, incompatibil, deoarece designul său ar trebui utilizat numai pentru profilarea reclamelor. Este, de asemenea, menționat în referința oficială
Utilizați un ID de publicitate numai pentru profilarea utilizatorilor sau pentru cazurile de utilizare a anunțurilor
Nu este doar de încredere pentru identificarea dispozitivului, dar trebuie să urmați și politica privind confidențialitatea utilizatorului în ceea ce privește urmărirea anunțurilor, care prevede clar că utilizatorul o poate reseta sau bloca în orice moment.
Așa că nici nu îl folosiți.
Deoarece nu puteți avea identificatorul de dispozitiv unic și de încredere static dorit la nivel global. Referința oficială pentru Android sugerează:
Utilizați un FirebaseInstanceId sau un GUID stocat privat ori de câte ori este posibil pentru toate celelalte cazuri de utilizare, cu excepția prevenirii fraudei la plată și a telefoniei.
Este unic pentru instalarea aplicației pe dispozitiv, așa că atunci când utilizatorul dezinstalează aplicația - este șters, deci nu este 100% fiabil, dar este cel mai bun lucru.
Pentru a utiliza FirebaseInstanceId adăugați cea mai recentă dependență de mesagerie Firebase în gradul dvs.
implementation 'com.google.firebase:firebase-messaging:20.2.4'
Și folosiți codul de mai jos într-un thread de fundal:
String reliableIdentifier = FirebaseInstanceId.getInstance().getId();
Dacă trebuie să stocați identificarea dispozitivului pe serverul dvs. la distanță, atunci nu o stocați așa cum este (text simplu), ci o haș cu sare.
Astăzi nu este doar o practică bună, ci trebuie să o faci prin lege, conform GDPR - identificatori și reglementări similare.
UUID.randomUUID() a Java, care depindea de natură bazată pe timp.
- person Nikita Kurtin; 25.02.2021
Blogul oficial pentru dezvoltatori Android are acum un articol complet despre acest subiect, Identificarea Instalări de aplicații.
La Google I/O, Reto Meier a lansat un răspuns solid despre cum să abordăm acest lucru, care ar trebui să răspundă nevoilor majorității dezvoltatorilor de a urmări utilizatorii din toate instalațiile. Anthony Nolan arată direcția în răspunsul său, dar m-am gândit să scriu abordarea completă, astfel încât alții să poată vedea cu ușurință cum să o facă (mi-a luat ceva timp să-mi dau seama de detalii).
Această abordare vă va oferi un ID de utilizator anonim, securizat, care va fi persistent pentru utilizator pe diferite dispozitive (pe baza contului Google principal) și pe parcursul instalărilor. Abordarea de bază este generarea unui ID de utilizator aleatoriu și stocarea acestuia în preferințele comune ale aplicațiilor. Apoi utilizați agentul de rezervă Google pentru a stoca preferințele partajate legate de contul Google în cloud.
Să trecem prin abordarea completă. În primul rând, trebuie să creăm o copie de rezervă pentru SharedPreferences folosind serviciul Android Backup. Începeți prin a vă înregistra aplicația prin http://developer.android.com/google/backup/signup.html.
Google vă va oferi o cheie de serviciu de rezervă pe care trebuie să o adăugați la manifest. De asemenea, trebuie să spuneți aplicației să folosească BackupAgent după cum urmează:
<application android:label="MyApplication"
android:backupAgent="MyBackupAgent">
...
<meta-data android:name="com.google.android.backup.api_key"
android:value="your_backup_service_key" />
</application>
Apoi, trebuie să creați agentul de rezervă și să îi spuneți să folosească agentul de ajutor pentru preferințe partajate:
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);
}
}
Pentru a finaliza backup-ul, trebuie să creați o instanță a BackupManager în Activitatea principală:
BackupManager backupManager = new BackupManager(context);
În cele din urmă, creați un ID de utilizator, dacă nu există deja și stocați-l în 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;
}
Acest User_ID va fi acum persistent în toate instalările, chiar dacă utilizatorul mută dispozitivul.
Pentru mai multe informații despre această abordare, consultați Discursul lui Reto.
Și pentru detalii complete despre cum să implementați agentul de rezervă, consultați Copia de rezervă a datelor. Recomand în special secțiunea din partea de jos despre testare, deoarece backup-ul nu are loc instantaneu, așa că pentru a testa trebuie să forțați backup-ul.
Cred că acesta este un mod sigur de a construi un schelet pentru un ID unic... verifică-l.
ID pseudo-unic, care funcționează pe toate dispozitivele Android Unele dispozitive nu au telefon (de exemplu, tablete) sau, dintr-un motiv oarecare, nu doriți să includeți permisiunea READ_PHONE_STATE. Puteți citi în continuare detalii precum versiunea ROM, numele producătorului, tipul procesorului și alte detalii hardware, care vor fi potrivite dacă doriți să utilizați ID-ul pentru verificarea cheii de serie sau în alte scopuri generale. ID-ul calculat în acest fel nu va fi unic: este posibil să găsiți două dispozitive cu același ID (pe baza aceluiași hardware și imagine ROM), dar schimbările în aplicațiile din lumea reală sunt neglijabile. În acest scop puteți folosi clasa 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
Majoritatea membrilor Build sunt șiruri, ceea ce facem aici este să le luăm lungimea și să o transformăm prin modulo într-o cifră. Avem 13 astfel de cifre și mai adăugăm două în față (35) pentru a avea aceeași dimensiune ID ca și IMEI (15 cifre). Există și alte posibilități aici sunt bune, aruncați o privire la aceste șiruri. Returnează ceva de genul 355715565309247. Nu este necesară nicio permisiune specială, ceea ce face această abordare foarte convenabilă.
(Informații suplimentare: tehnica prezentată mai sus a fost copiată dintr-un articol de pe Pocket Magic.)
Următorul cod returnează numărul de serie al dispozitivului folosind un API Android ascuns. Dar, acest cod nu funcționează pe Samsung Galaxy Tab, deoarece „ro.serialno” nu este setat pe acest dispozitiv.
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) {
}
Folosind codul de mai jos, puteți obține ID-ul unic de dispozitiv al unui dispozitiv cu sistem de operare Android ca șir.
deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Un câmp Serial a fost adăugat la clasa Build la nivelul API 9 (Android 2.3 - Turtă dulce). Documentația spune că reprezintă numărul de serie hardware. Astfel, ar trebui să fie unic, dacă există pe dispozitiv.
Totuși, nu știu dacă este acceptat (=nu nul) de toate dispozitivele cu nivel API >= 9.
Un lucru aș adăuga - am una dintre acele situații unice.
Folosind:
deviceId = Secure.getString(this.getContext().getContentResolver(), Secure.ANDROID_ID);
Se pare că, deși tableta mea Viewsonic G raportează un DeviceID care nu este Null, fiecare tabletă G raportează același număr.
O face interesantă să joci „Pocket Empires”, care îți oferă acces instantaneu la contul cuiva, pe baza ID-ului dispozitivului „unic”.
Dispozitivul meu nu are un radio celular.
Pentru instrucțiuni detaliate despre cum să obțineți un identificator unic pentru fiecare dispozitiv Android de pe care este instalată aplicația dvs., consultați postarea oficială pe blogul dezvoltatorilor Android Identificarea instalărilor de aplicații.
Se pare că cel mai bun mod este să generați unul singur la instalare și să îl citiți ulterior când aplicația este relansată.
Eu personal consider acest lucru acceptabil, dar nu ideal. Niciun identificator furnizat de Android nu funcționează în toate cazurile, deoarece majoritatea depind de stările radio ale telefonului (Wi-Fi activat/dezactivat, pornit/dezactivat mobil, Bluetooth activat/dezactivat). Celelalte, cum ar fi Settings.Secure.ANDROID_ID, trebuie implementate de producător și nu sunt garantate a fi unice.
Următorul este un exemplu de scriere a datelor într-un fișier de instalare care ar fi stocat împreună cu orice alte date pe care aplicația le salvează local.
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();
}
}
Adăugați codul de mai jos în fișierul clasei:
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);
Adăugați în AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Există o mulțime de abordări diferite pentru a rezolva aceste ANDROID_ID probleme (poate fi null uneori sau dispozitivele unui anumit model returnează întotdeauna același ID) cu argumente pro și contra:
- Implementarea unui algoritm personalizat de generare a ID-ului (bazat pe proprietățile dispozitivului care ar trebui să fie statice și nu se vor schimba -> cine știe)
- Abuzul de alte ID-uri, cum ar fi IMEI, numărul de serie, adresa Wi-Fi/Bluetooth-MAC (se vor nu există pe toate dispozitivele sau devin necesare permisiuni suplimentare)
Eu prefer să folosesc o implementare OpenUDID existentă (vezi https://github.com/ylechelle/OpenUDID) pentru Android (consultați https://github.com/vieux/OpenUDID). Este ușor de integrat și folosește ANDROID_ID cu alternative pentru problemele menționate mai sus.
ID-ul unic de dispozitiv al unui dispozitiv cu sistem de operare Android ca String, folosind TelephonyManager și ANDROID_ID, este obținut prin:
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);
}
Dar recomand cu tărie o metodă sugerată de Google, consultați Identificare Instalări de aplicații.
Există peste 30 de răspunsuri aici și unele sunt aceleași, iar altele sunt unice. Acest răspuns se bazează pe câteva dintre aceste răspunsuri. Unul dintre ele este răspunsul lui @Lenn Dolling.
Combină 3 ID-uri și creează un șir hexadecimal de 32 de cifre. A funcționat foarte bine pentru mine.
3 ID-uri sunt:
Pseudo-ID - Este generat pe baza specificațiilor dispozitivului fizic
ANDROID_ID - Settings.Secure.ANDROID_ID
Adresa Bluetooth - Adresa adaptorului Bluetooth
Va returna ceva de genul acesta: 551F27C060712A72730B0A0F734064B1
Notă: puteți adăuga oricând mai multe ID-uri la șirul longId. De exemplu, Serial #. adresa adaptorului wifi. IMEI. În acest fel, îl faceți mai unic pentru fiecare dispozitiv.
@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 și stocarea acestuia într-un fișier, îl va face cel mai unic identificator : String uuid = UUID.randomUUID().toString();
- person Mousa Alfhaily; 11.04.2017
longId. Schimbați acea linie astfel: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString(); Acest lucru garantează că ID-ul generat va fi unic.
- person ᴛʜᴇᴘᴀᴛᴇʟ; 03.04.2019
Ce zici de IMEI. Este unic pentru Android sau alte dispozitive mobile.
Iată cum generez ID-ul unic:
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;
}
Cei doi cenți ai mei - NB, acesta este pentru un ID unic de dispozitiv (err) - nu pentru cel de instalare, așa cum se discută în Blogul dezvoltatorilor Android.
De reținut că soluția furnizată de @emmby revine într-un ID per aplicație, deoarece SharedPreferences nu sunt sincronizate între procese (consultați aici și aici). Așa că am evitat acest lucru cu totul.
În schimb, am încapsulat diferitele strategii pentru obținerea unui ID (dispozitiv) într-o enumerare - schimbarea ordinii constantelor enumerare afectează prioritatea diferitelor modalități de obținere a ID-ului. Primul ID non-null este returnat sau se aruncă o excepție (conform bunelor practici Java de a nu da un sens null). Așa că, de exemplu, am primul TELEPHONY - dar o alegere implicită bună ar fi 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);
}
}
}
O altă modalitate este să utilizați /sys/class/android_usb/android0/iSerial într-o aplicație fără nicio permisiune.
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
Pentru a face acest lucru în Java, ar trebui doar să folosiți un FileInputStream pentru a deschide fișierul iSerial și a citi caracterele. Doar asigurați-vă că îl includeți într-un handler de excepții, deoarece nu toate dispozitivele au acest fișier.
Se știe că cel puțin următoarele dispozitive au acest fișier lizibil în întreaga lume:
- Galaxy Nexus
- Nexus S
- Motorola Xoom 3G
- Toshiba AT300
- HTC One V
- Mini MK802
- Samsung Galaxy S II
De asemenea, puteți vedea articolul meu de blog Scurgeri de hardware Android număr de serie către aplicații neprivilegiate, unde discut despre ce alte fișiere sunt disponibile pentru informații.
TelephonyManger.getDeviceId() Returnează ID-ul unic al dispozitivului, de exemplu, IMEI pentru GSM și MEID sau ESN pentru telefoanele CDMA.
final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String myAndroidDeviceId = mTelephony.getDeviceId();
Dar recomand să folosești:
Settings.Secure.ANDROID_ID care returnează ID-ul Android ca un șir hexadecimal unic de 64 de biți.
String myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID);
Uneori, TelephonyManger.getDeviceId() va returna null, așa că pentru a asigura un ID unic, veți folosi această metodă:
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;
}
ID de instanță Google
Lansat la I/O 2015; pe Android necesită servicii de redare 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
Se pare că Google intenționează ca acest ID să fie utilizat pentru a identifica instalările pe Android, Chrome și iOS.
Identifică o instalare mai degrabă decât un dispozitiv, dar, din nou, ANDROID_ID (care este răspunsul acceptat) acum nu mai identifică nici dispozitivele. Cu timpul de execuție ARC este generat un nou ANDROID_ID pentru fiecare instalare (detalii aici), la fel ca acest nou ID de instanță. De asemenea, cred că identificarea instalațiilor (nu a dispozitivelor) este ceea ce caută de fapt majoritatea dintre noi.
Avantajele ID-ului instanței
Mi se pare că Google intenționează ca acesta să fie utilizat în acest scop (identificarea instalărilor dvs.), este multiplatformă și poate fi folosit în mai multe alte scopuri (consultați linkurile de mai sus).
Dacă utilizați GCM, în cele din urmă va trebui să utilizați acest ID de instanță, deoarece aveți nevoie de el pentru a obține indicativul GCM (care înlocuiește vechiul ID de înregistrare GCM).
Dezavantajele/problemele
În implementarea curentă (GPS 7.5), ID-ul instanței este preluat de pe un server atunci când aplicația dvs. îl solicită. Aceasta înseamnă că apelul de mai sus este un apel de blocare - în testarea mea neștiințifică durează 1-3 secunde dacă dispozitivul este online și 0,5 - 1,0 secunde dacă este offline (probabil că acesta este cât timp așteaptă înainte de a renunța și de a genera un ID aleatoriu). Acesta a fost testat în America de Nord pe Nexus 5 cu Android 5.1.1 și GPS 7.5.
Dacă utilizați ID-ul în scopurile pe care le intenționează - de ex. autentificarea aplicației, identificarea aplicației, GCM - Cred că aceste 1-3 secunde ar putea fi o pacoste (în funcție de aplicația dvs., desigur).
Pentru recunoașterea hardware a unui anumit dispozitiv Android, puteți verifica adresele MAC.
poti face asa:
în AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
acum in codul tau:
List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface interface : interfacesList) {
// This will give you the interface MAC ADDRESS
interface.getHardwareAddress();
}
În fiecare dispozitiv Android există cel puțin o interfață „wlan0” care este cipul WI-FI. Acest cod funcționează chiar și atunci când WI-FI nu este pornit.
P.S. Sunt o grămadă de alte interfețe pe care le veți obține din lista care conține MACS, dar acest lucru se poate schimba între telefoane.
Folosesc următorul cod pentru a obține IMEI sau pentru a folosi Secure.ANDROID_ID ca alternativă, când dispozitivul nu are capabilități de telefon:
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);
Pentru a înțelege ID-urile unice disponibile pe dispozitivele Android. Utilizați acest ghid oficial.
Cele mai bune practici pentru identificatorii unici:
IMEI, adrese Mac, ID de instanță, GUID-uri, SSAID, ID de publicitate, API Safety Net pentru a verifica dispozitivele.
https://developer.android.com/training/articles/user-data-ids
Google are acum un ID de publicitate.
Acesta poate, de asemenea, fi folosit, dar rețineți că:
ID-ul de publicitate este un ID specific utilizatorului, unic, resetabil
și
permite utilizatorilor să își resetați identificatorul sau să renunțe la anunțurile bazate pe interese din aplicațiile Google Play.
Deci, deși acest ID se poate schimba, se pare că în curând s-ar putea să nu avem de ales, depinde de scopul acestui id.
Mai multe informații @ develper.android
Copiați și inserați codul aici
HTH
1.Utilizați managerul de telefonie, care oferă un ID unic (adică IMEI). Vezi exemplul,
import android.telephony.TelephonyManager;
import android.content.Context;
// ...
TelephonyManager telephonyManager;
telephonyManager = (TelephonyManager) getSystemService(Context.
TELEPHONY_SERVICE);
/*
* getDeviceId() returns the unique device ID.
* For example,the IMEI for GSM and the MEID or ESN for CDMA phones.
*/
String deviceId = telephonyManager.getDeviceId();
/*
* getSubscriberId() returns the unique subscriber ID,
*/
String subscriberId = telephonyManager.getSubscriberId();
Acest lucru necesită android.permission.READ_PHONE_STATE utilizatorului dvs., ceea ce poate fi greu de justificat în funcție de tipul de aplicație pe care ați făcut-o.
Dispozitivele fără servicii de telefonie, cum ar fi tabletele, trebuie să raporteze un ID unic de dispozitiv care este disponibil prin
android.os.Build.SERIALîncepând cu Android 2.3 Gingerbread. Unele telefoane care au servicii de telefonie pot defini, de asemenea, un număr de serie. Deoarece nu toate dispozitivele Android au un număr de serie, această soluție nu este de încredere.La prima pornire a dispozitivului, este generată și stocată o valoare aleatorie. Această valoare este disponibilă prin
Settings.Secure.ANDROID_ID. Este un număr pe 64 de biți care ar trebui să rămână constant pe durata de viață a unui dispozitiv.ANDROID_IDpare o alegere bună pentru un identificator unic de dispozitiv, deoarece este disponibil pentru smartphone-uri și tablete. Pentru a prelua valoarea, puteți utiliza următorul cod,String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
Cu toate acestea, valoarea se poate modifica dacă se efectuează o resetare din fabrică pe dispozitiv. Există, de asemenea, o eroare cunoscută cu un telefon popular de la un producător, în care fiecare instanță are același ANDROID_ID. În mod clar, soluția nu este 100% fiabilă.
- Utilizați UUID. Deoarece cerința pentru majoritatea aplicațiilor este identificarea unei anumite instalări și nu a unui dispozitiv fizic, o soluție bună pentru a obține ID-ul unic pentru un utilizator dacă folosește clasa UUID. Următoarea soluție a fost prezentată de Reto Meier de la Google într-o prezentare Google I/O,
SharedPreferences sharedPrefs = context.getSharedPreferences(
PREF_UNIQUE_ID, Context.MODE_PRIVATE);
uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
Actualizare: opțiunea #1 și #2 nu mai sunt disponibile după Android 10, deoarece confidențialitatea este actualizată de către Google. ca opțiunea 2 și 3 necesită permisiunea critică.
DeviceInfoProvider nu face parte din Android SDK
- person user924; 06.02.2020
ID-ul mac al dispozitivului Android este, de asemenea, un id unic. Nu se va schimba chiar dacă dispozitivul în sine este formatat.
Utilizați următorul cod pentru a obține ID-ul mac:
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();
De asemenea, nu uitați să adăugați permisiunile corespunzătoare în AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
Doar un avertisment pentru toți cei care citesc care caută mai multe informații actualizate. Cu Android O, există unele modificări ale modului în care sistemul gestionează aceste ID-uri.
https://android-developers.googleblog.com/2017/04/changes-to-device-identifiers-in.html
tl;dr Serial va necesita permisiunea TELEFON, iar ID-ul Android se va schimba pentru diferite aplicații, în funcție de numele și semnătura pachetului.
Și, de asemenea, Google a creat un document frumos care oferă sugestii despre când să utilizați ID-urile hardware și software.
https://developer.android.com/training/articles/user-data-ids.html
În mod normal, folosesc ID-ul unic al dispozitivului pentru aplicațiile mele. Dar uneori folosesc IMEI. Ambele sunt numere unice.
pentru a obține IMEI (identificatorul internațional de echipament mobil)
public String getIMEI(Activity activity) {
TelephonyManager telephonyManager = (TelephonyManager) activity
.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
pentru a obține ID unic al dispozitivului
public String getDeviceUniqueID(Activity activity){
String device_unique_id = Secure.getString(activity.getContentResolver(),
Secure.ANDROID_ID);
return device_unique_id;
}
Am întâlnit această întrebare în urmă cu câțiva ani și am învățat să implementez o soluție generalizată bazată pe diferite răspunsuri.
Am folosit soluția generalizată de câțiva ani, într-un produs din lumea reală. Imi serveste destul de bine pana acum. Iată fragmentul de cod, bazat pe diferite răspunsuri furnizate.
Rețineți, getEmail va returna null de cele mai multe ori, deoarece nu am cerut permisiunea în mod explicit.
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;
}
Nu este recomandat ca deviceId poate fi folosit ca urmărire în mâinile terților, dar aceasta este o altă modalitate.
@SuppressLint("HardwareIds")
private String getDeviceID() {
deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(),
Settings.Secure.ANDROID_ID);
return deviceId;
}
Iată un răspuns simplu pentru a obține AAID, testat funcțional corect în iunie 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();
citește răspunsul complet în detaliu aici:
Obțineți DUUID-ul dispozitivului, numărul de model cu numele mărcii și numărul său de versiune cu ajutorul funcției de mai jos.
Funcționează în Android 10 perfect și nu este nevoie să permiteți permisiunea de citire a stării telefonului.
Fragmente de cod:
private void fetchDeviceInfo() {
String uniquePseudoID = "35" +
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.HOST.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10;
String serial = Build.getRadioVersion();
String uuid=new UUID(uniquePseudoID.hashCode(), serial.hashCode()).toString();
String brand=Build.BRAND;
String modelno=Build.MODEL;
String version=Build.VERSION.RELEASE;
Log.e(TAG, "fetchDeviceInfo: \n "+
"\n uuid is : "+uuid+
"\n brand is: "+brand+
"\n model is: "+modelno+
"\n version is: "+version);
}
Funcția Apelați deasupra și pentru a verifica rezultatul codului de mai sus. vă rugăm să vedeți pisica de jurnal în Android Studio. Arata ca mai jos:
Pentru a include Android 9, am o singură idee care ar putea funcționa și care (probabil) nu încalcă niciun termen, necesită permisiuni și funcționează în toate instalările și aplicațiile.
Amprentarea digitală care implică un server ar trebui să poată identifica un dispozitiv în mod unic. Combinația de informații hardware + aplicații instalate și timpii de instalare ar trebui să facă truc. Timpul de instalare nu se modifică decât dacă o aplicație este dezinstalată și instalată din nou. Dar acest lucru ar trebui făcut pentru toate aplicațiile de pe dispozitiv pentru a nu putea identifica dispozitivul (adică după o resetare din fabrică).
Iată cum aș proceda:
- Extrageți informații despre hardware, numele pachetelor de aplicații și primele instalări.
Iată cum extrageți toate aplicațiile de pe Android (nu sunt necesare permisiuni):
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();
}
}
- Este posibil să doriți să faceți un hash pentru fiecare nume de pachet și combinația de marcaj de timp al instalării, înainte de a-l trimite la server, deoarece poate fi sau nu ceea ce utilizatorul a instalat pe dispozitiv.
- Unele aplicații (de fapt multe) sunt aplicații de sistem. Este posibil ca acestea să aibă același marcaj temporal de instalare, care se potrivește cu cea mai recentă actualizare a sistemului după o resetare din fabrică. Deoarece au același timp de instalare, acestea nu pot fi instalate de utilizator și pot fi filtrate.
- Trimiteți informațiile către server și lăsați-l să caute cea mai apropiată potrivire dintre informațiile stocate anterior. Trebuie să stabiliți un prag atunci când comparați cu informațiile stocate anterior pe dispozitiv, deoarece aplicațiile sunt instalate și dezinstalate. Dar presupunerea mea este că acest prag poate fi foarte scăzut, deoarece orice nume de pachet și combinația de marcaj temporal de instalare pentru prima dată va fi destul de unică pentru un dispozitiv, iar aplicațiile nu sunt instalate și dezinstalate atât de frecvent. Având mai multe aplicații, crește probabilitatea de a fi unic.
- Returnați ID-ul unic generat pentru meci sau generați un ID unic, stocați cu informații despre dispozitiv și returnați acest nou ID.
NB: Aceasta este o metodă netestată și nedovedită! Sunt încrezător că va funcționa, dar sunt, de asemenea, destul de sigur că, dacă acest lucru va ajunge, o vor închide într-un fel sau altul.
Daca adaugati:
Settings.Secure.getString(context.contentResolver,
Settings.Secure.ANDROID_ID)
Android Lint vă va oferi următorul avertisment:
Utilizarea getString pentru a obține identificatori de dispozitiv nu este recomandată. Informații de inspecție: utilizarea acestor identificatori de dispozitiv nu este recomandată decât pentru prevenirea fraudei de mare valoare și cazuri de utilizare avansate pentru telefonie. Pentru cazurile de utilizare în publicitate, utilizați AdvertisingIdClient$Info#getId și pentru analize, utilizați InstanceId#getId.
Deci, ar trebui să evitați să utilizați acest lucru.
După cum este menționat în documentația pentru dezvoltatori Android :
1: Evitați utilizarea identificatorilor hardware.
În majoritatea cazurilor de utilizare, puteți evita utilizarea identificatorilor hardware, cum ar fi SSAID (ID Android) și IMEI, fără a limita funcționalitatea necesară.
2: Folosiți un ID de publicitate numai pentru profilarea utilizatorilor sau pentru cazurile de utilizare pentru anunțuri.
Când utilizați un ID de publicitate, respectați întotdeauna selecțiile utilizatorilor cu privire la urmărirea anunțurilor. De asemenea, asigurați-vă că identificatorul nu poate fi conectat la informații de identificare personală (PII) și evitați resetarea ID-ului publicitar.
3: Folosiți un ID de instanță sau un GUID stocat privat ori de câte ori este posibil pentru toate celelalte cazuri de utilizare, cu excepția prevenirii fraudei la plată și a telefoniei.
Pentru marea majoritate a cazurilor de utilizare non-reclame, un ID de instanță sau un GUID ar trebui să fie suficient.
4: Utilizați API-uri adecvate pentru cazul dvs. de utilizare pentru a minimiza riscul de confidențialitate.
Utilizați API-ul DRM pentru protecția conținutului de mare valoare și API-urile SafetyNet pentru protecția împotriva abuzurilor. API-urile SafetyNet sunt cea mai simplă modalitate de a determina dacă un dispozitiv este autentic, fără a implica riscuri de confidențialitate.
String SERIAL_NUMER = Build.SERIAL;
Returnează NUMĂRUL DE SERIE ca șir unic pentru fiecare dispozitiv.
Numărul de serie este un ID unic de dispozitiv disponibil prin 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;
}
Asigurați-vă că aveți permisiunea READ_PHONE_STATE înainte de a apela getSerial().
NOTĂ:- este nu este disponibil pentru dispozitive fără telefonie (cum ar fi tabletele numai cu Wi-Fi).
Build.SERIAL (sau Build.getSerial()) nu este întotdeauna disponibil. Mai multe informații sunt disponibile în postarea de blog Modificări ale Identificatori de dispozitiv în Android O. De asemenea, merită citit: Cele mai bune practici pentru identificatorii unici.
- person Ted Hopp; 14.12.2017
Pentru a fi complet, iată cum puteți obține Id în Xamarin.Android și C#:
var id = Settings.Secure.GetString(ContentResolver, Settings.Secure.AndroidId);
Sau dacă nu vă aflați într-un Activity:
var id = Settings.Secure.GetString(context.ContentResolver, Settings.Secure.AndroidId);
Unde context este transmis în context.
android.telephony.TelephonyManager.getDeviceId()
Aceasta va returna orice șir care identifică în mod unic dispozitivul (IMEI pe GSM, MEID pentru CDMA).
Veți avea nevoie de următoarea permisiune în AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Da, fiecare dispozitiv Android are numere de serie unice pe care le puteți obține din acest cod. Build.SERIAL. Rețineți că a fost adăugat doar la nivelul API 9 și este posibil să nu fie prezent pe toate dispozitivele. Pentru a obține un ID unic pe platformele anterioare, va trebui să citiți ceva precum adresa MAC sau IMEI.
Verificați SystemInfo.deviceUniqueIdentifier
Documentație: http://docs.unity3d.com/Documentation/ScriptReference/SystemInfo-deviceUniqueIdentifier.html
Un identificator unic de dispozitiv. Este garantat să fie unic pentru fiecare dispozitiv (numai citire).
iOS: pe dispozitivele pre-iOS7 va returna hash-ul adresei MAC. Pe dispozitivele iOS7 va fi UIDevice identifierForVendor sau, dacă nu reușește din orice motiv, ASIdentifierManager advertisingIdentifier.
Obțineți ID-ul dispozitivului o singură dată, apoi stocați-l într-o bază de date sau într-un fișier. În acest caz, dacă este prima pornire a aplicației, generează un ID și îl stochează. Data viitoare, va lua doar ID-ul stocat în fișier.
Pentru a obține un ID de utilizator, puteți utiliza Biblioteca de licențiere Google Play.
Pentru a descărca această bibliotecă, deschideți SDK Manager => SDK Tools. Calea către fișierele de bibliotecă descărcate este:
path_to_android_sdk_on_your_pc/extras/google/market_licensing/library
Includeți biblioteca în proiectul dvs. (puteți să copiați pur și simplu fișierele acesteia).
În continuare, aveți nevoie de implementarea interfeței Policy (puteți utiliza pur și simplu unul dintre cele două fișiere din bibliotecă: ServerManagedPolicy sau StrictPolicy).
Id-ul de utilizator vă va fi furnizat în cadrul funcției processServerResponse():
public void processServerResponse(int response, ResponseData rawData) {
if(rawData != null) {
String userId = rawData.userId
// use/save the value
}
// ...
}
Apoi, trebuie să construiți LicenseChecker cu o politică și să apelați funcția checkAccess(). Utilizați MainActivity.java ca exemplu despre cum să faceți acest lucru. MainActivity.java se află în interiorul acestui folder:
path_to_android_sdk_on_your_pc/extras/google/market_licensing/sample/src/com/example/android/market/licensing
Nu uitați să adăugați permisiunea CHECK_LICENSE la AndroidManifest.xml.
Mai multe despre Biblioteca de licențiere: https://developer.android.com/google/play/licensing
Android restricționează ID-ul legat de hardware după Android O, prin urmare, Android_Id este soluția pentru id-ul unic, dar are o problemă când reflectă dispozitivul, va genera un nou android_id pentru a depăși această problemă, putem folosi DRUMID-ul.
val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
val drumIDByteArray = MediaDrm(WIDEVINE_UUID).getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID)
val drumID = android.util.Base64.encodeToString(drumIDByteArray,android.util.Base64.DEFAULT)
Veți obține adresa wifi mac utilizând următorul cod, indiferent dacă ați folosit o adresă randomizată când ați încercat să vă conectați la wifi sau nu și indiferent dacă wifi-ul a fost pornit sau oprit.
Am folosit o metodă din linkul de mai jos și am adăugat o mică modificare pentru a obține adresa exactă în loc de cea randomizată:
Obținerea adresei MAC în Android 6.0
public static String getMacAddr() {
StringBuilder res1 = new StringBuilder();
try {
List<NetworkInterface> all =
Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface nif : all) {
if (!nif.getName().equalsIgnoreCase("p2p0")) continue;
byte[] macBytes = nif.getHardwareAddress();
if (macBytes == null) {
continue;
}
res1 = new StringBuilder();
for (byte b : macBytes) {
res1.append(String.format("%02X:",b));
}
if (res1.length() > 0) {
res1.deleteCharAt(res1.length() - 1);
}
}
} catch (Exception ex) {
}
return res1.toString();
}

ANDROID_ID, asigurați-vă că citiți acest răspuns și this bug /a>. - person Dheeraj Vepakomma   schedule 16.01.2013