Gibt es eine eindeutige Android-Geräte-ID?

2751

Haben Android-Geräte eine eindeutige ID, und wenn ja, wie kann man auf einfache Weise mit Java darauf zugreifen?

Tyler
quelle
38
Wenn Sie verwenden ANDROID_ID, lesen Sie unbedingt diese Antwort und diesen Fehler .
Dheeraj Vepakomma
Wenn Sie eine Lösung im Jahr 2020 benötigen, sollten Sie die Android-
IDs

Antworten:

2024

Settings.Secure#ANDROID_IDGibt die Android-ID als eindeutige 64-Bit-Hex-Zeichenfolge für jeden Benutzer zurück .

import android.provider.Settings.Secure;

private String android_id = Secure.getString(getContext().getContentResolver(),
                                                        Secure.ANDROID_ID); 
Anthony Forloney
quelle
476
Es ist bekannt, dass es manchmal null ist. Es ist dokumentiert als "kann sich beim Zurücksetzen auf die Werkseinstellungen ändern". Die Verwendung erfolgt auf eigenes Risiko und kann problemlos auf einem gerooteten Telefon geändert werden.
Seva Alekseyev
18
Ich denke, wir müssen vorsichtig sein, wenn wir ANDROID_ID in Hash in der ersten Antwort verwenden, da es möglicherweise nicht festgelegt wird, wenn die App zum ersten Mal ausgeführt wird, später festgelegt wird oder sich sogar theoretisch ändert, daher kann sich die eindeutige ID ändern
46
Beachten
Sie, dass
35
ANDROID_ID identifiziert ein Gerät nicht mehr eindeutig (ab 4.2): stackoverflow.com/a/13465373/150016
Tom
1145

UPDATE : Seit den letzten Versionen von Android wurden viele der Probleme ANDROID_IDbehoben, und ich glaube, dass dieser Ansatz nicht mehr erforderlich ist. Bitte werfen Sie einen Blick auf Anthonys Antwort .

Vollständige Offenlegung: Meine App hat ursprünglich den folgenden Ansatz verwendet, verwendet diesen Ansatz jedoch nicht mehr. Wir verwenden jetzt den im Android Developer Blog- Eintrag beschriebenen Ansatz, auf den die Antwort von emmby verweist (nämlich Generieren und Speichern von a UUID#randomUUID()).


Es gibt viele Antworten auf diese Frage, von denen die meisten nur "teilweise" funktionieren, und das ist leider nicht gut genug.

Basierend auf meinen Gerätetests (alle Telefone, von denen mindestens eines nicht aktiviert ist):

  1. Alle getesteten Geräte gaben einen Wert für zurück TelephonyManager.getDeviceId()
  2. Alle GSM-Geräte (alle mit einer SIM-Karte getestet) gaben einen Wert für zurück TelephonyManager.getSimSerialNumber()
  3. Alle CDMA-Geräte gaben null zurück getSimSerialNumber()(wie erwartet)
  4. Alle Geräte mit einem hinzugefügten Google-Konto haben einen Wert für zurückgegeben ANDROID_ID
  5. Alle CDMA-Geräte haben für beide den gleichen Wert (oder die Ableitung des gleichen Werts) zurückgegeben ANDROID_IDund TelephonyManager.getDeviceId()- solange während der Einrichtung ein Google-Konto hinzugefügt wurde.
  6. Ich hatte noch keine Gelegenheit, GSM-Geräte ohne SIM-Karte, ein GSM-Gerät ohne Google-Konto oder eines der Geräte im Flugzeugmodus zu testen.

Wenn Sie also etwas Einzigartiges für das Gerät selbst wünschen , TM.getDeviceId() sollte dies ausreichen. Offensichtlich sind einige Benutzer paranoider als andere, daher kann es nützlich sein, einen oder mehrere dieser Bezeichner zu hashen, damit die Zeichenfolge für das Gerät praktisch immer noch eindeutig ist, das tatsächliche Gerät des Benutzers jedoch nicht explizit identifiziert. Verwenden Sie beispielsweise in String.hashCode()Kombination mit einer 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();

könnte zu etwas führen wie: 00000000-54b3-e7c7-0000-000046bffd97

Es funktioniert gut genug für mich.

Vergessen Sie nicht, dass Sie, wie Richard weiter unten erwähnt, eine Berechtigung zum Lesen der TelephonyManagerEigenschaften benötigen. Fügen Sie diese also Ihrem Manifest hinzu:

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

libs importieren

import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.View;
Joe
quelle
151
Telefoniebasierte ID wird auf Tablet-Geräten nicht vorhanden sein, oder?
Seva Alekseyev
22
Daher habe ich gesagt, dass die meisten nicht immer funktionieren :) Ich habe noch keine Antwort auf diese Frage gefunden, die für alle Geräte, alle Gerätetypen und alle Hardwarekonfigurationen zuverlässig ist. Deshalb ist diese Frage zunächst hier. Es ist ziemlich klar, dass es dafür keine End-All-Be-All-Lösung gibt. Einzelne Gerätehersteller verfügen möglicherweise über Seriennummern von Geräten, diese sind jedoch für uns nicht verfügbar, und dies ist keine Voraussetzung. So bleibt uns das, was uns zur Verfügung steht.
Joe
31
Das Codebeispiel funktioniert hervorragend. Denken Sie daran <uses-permission android:name="android.permission.READ_PHONE_STATE" />, der Manifestdatei etwas hinzuzufügen . Beim Speichern in einer Datenbank ist die zurückgegebene Zeichenfolge 36 Zeichen lang.
Richard
10
Beachten
Sie, dass
18
@softarn: Ich glaube , was Sie sich beziehen ist der Android - Entwickler - Blog, die bereits verknüpft emmby, was erklärt , was Sie versuchen , zu sagen , so sollten Sie vielleicht einfach seinen Kommentar stattdessen upvoted haben. Wie auch immer, wie Emmby in seiner Antwort erwähnt, gibt es auch bei den Blog-Informationen immer noch Probleme. In der Frage wird nach einer eindeutigen GERÄTE-ID (keine Installations- ID ) gefragt , daher stimme ich Ihrer Aussage nicht zu. Der Blog geht davon aus, dass Sie nicht unbedingt das Gerät verfolgen möchten , während die Frage genau das verlangt. Ansonsten stimme ich dem Blog zu.
Joe
438

Letzte Aktualisierung: 02.06.15


Nachdem ich jeden Stack Overflow-Beitrag über das Erstellen einer eindeutigen ID, das Google-Entwicklerblog und die Android-Dokumentation gelesen habe, habe ich das Gefühl, dass die "Pseudo-ID" die bestmögliche Option ist.

Hauptproblem: Hardware vs Software

Hardware

  • Benutzer können ihre Hardware, ihr Android-Tablet oder ihr Telefon ändern, sodass eindeutige IDs basierend auf der Hardware keine guten Ideen für TRACKING USERS sind
  • Für TRACKING HARDWARE ist dies eine großartige Idee

Software

  • Benutzer können ihr ROM löschen / ändern, wenn sie gerootet sind
  • Sie können Benutzer plattformübergreifend verfolgen (iOS, Android, Windows und Web).
  • Der beste Wunsch, einen einzelnen Benutzer mit seiner Zustimmung aufzuspüren, besteht darin, ihn einfach anmelden zu lassen (dies mit OAuth nahtlos zu machen).

Gesamtaufschlüsselung mit Android

- Gewährleistung der Eindeutigkeit (einschließlich gerooteter Geräte) für API> = 9/10 (99,5% der Android-Geräte)

- Keine zusätzlichen Berechtigungen

Pseudocode:

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)

Vielen Dank an @stansult für die Veröffentlichung aller unserer Optionen (in dieser Frage zum Stapelüberlauf ).

Liste der Optionen - Gründe, warum / warum sie nicht verwendet werden:

  • Benutzer-E-Mail - Software

    • Benutzer könnte E-Mail ändern - sehr unwahrscheinlich
    • API 5+ <uses-permission android:name="android.permission.GET_ACCOUNTS" />oder
    • API 14+ <uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_CONTACTS" />( So erhalten Sie die primäre E-Mail-Adresse des Android-Geräts )
  • Benutzer Telefonnummer - Software

    • Benutzer könnten Telefonnummern ändern - sehr unwahrscheinlich
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • IMEI - Hardware (nur Telefone, Bedürfnisse android.permission.READ_PHONE_STATE)

    • Die meisten Benutzer hassen die Tatsache, dass in der Berechtigung "Telefonanrufe" steht. Einige Benutzer geben schlechte Bewertungen ab, weil sie glauben, dass Sie einfach ihre persönlichen Daten stehlen, wenn Sie wirklich nur die Installation von Geräten verfolgen möchten. Es ist offensichtlich, dass Sie Daten sammeln.
    • <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  • Android ID - Hardware (kann null sein, kann sich beim Zurücksetzen auf die Werkseinstellungen ändern, kann auf einem gerooteten Gerät geändert werden)

    • Da es 'null' sein kann, können wir nach 'null' suchen und seinen Wert ändern. Dies bedeutet jedoch, dass es nicht mehr eindeutig ist.
    • Wenn Sie einen Benutzer mit einem Gerät haben, das auf die Werkseinstellungen zurückgesetzt wurde, hat sich der Wert möglicherweise auf dem gerooteten Gerät geändert oder geändert, sodass möglicherweise doppelte Einträge vorhanden sind, wenn Sie Benutzerinstallationen verfolgen.
  • WLAN MAC Address - Hardware (benötigt android.permission.ACCESS_WIFI_STATE)

    • Dies könnte die zweitbeste Option sein, aber Sie sammeln und speichern immer noch eine eindeutige Kennung, die direkt von einem Benutzer stammt. Dies ist offensichtlich, dass Sie Daten sammeln.
    • <uses-permission android:name="android.permission.ACCESS_WIFI_STATE "/>
  • Bluetooth MAC Address - Hardware (Geräte mit Bluetooth, benötigt android.permission.BLUETOOTH)

    • Die meisten Anwendungen auf dem Markt verwenden kein Bluetooth. Wenn Ihre Anwendung kein Bluetooth verwendet und Sie dies einschließen, kann der Benutzer misstrauisch werden.
    • <uses-permission android:name="android.permission.BLUETOOTH "/>
  • Pseudo-Unique ID - Software (für alle Android-Geräte)

    • Sehr gut möglich, kann Kollisionen enthalten - Siehe meine Methode unten!
    • Auf diese Weise können Sie vom Benutzer eine "fast eindeutige" ID erhalten, ohne etwas Privates zu übernehmen. Sie können Ihre eigene anonyme ID aus Geräteinformationen erstellen.

Ich weiß, dass es keinen „perfekten“ Weg gibt, eine eindeutige ID zu erhalten, ohne Berechtigungen zu verwenden. Manchmal müssen wir jedoch nur die Geräteinstallation wirklich verfolgen. Wenn es darum geht, eine eindeutige ID zu erstellen, können wir eine "pseudo-eindeutige ID" erstellen, die ausschließlich auf Informationen basiert, die uns die Android-API ohne Verwendung zusätzlicher Berechtigungen gibt. Auf diese Weise können wir dem Benutzer Respekt entgegenbringen und versuchen, auch eine gute Benutzererfahrung zu bieten.

Mit einer pseudo-eindeutigen ID stoßen Sie wirklich nur auf die Tatsache, dass es möglicherweise Duplikate gibt, basierend auf der Tatsache, dass es ähnliche Geräte gibt. Sie können die kombinierte Methode optimieren, um sie einzigartiger zu machen. Einige Entwickler müssen jedoch die Geräteinstallationen nachverfolgen. Dies führt den Trick oder die Leistung auf der Grundlage ähnlicher Geräte aus.

API> = 9:

Wenn das Android-Gerät API 9 oder höher ist, ist dies aufgrund des Felds "Build.SERIAL" garantiert eindeutig.

Denken Sie daran, Sie verpassen technisch gesehen nur etwa 0,5% der Benutzer mit API <9 . Sie können sich also auf den Rest konzentrieren: Dies sind 99,5% der Benutzer!

API <9:

Wenn das Android-Gerät des Benutzers niedriger als API 9 ist; Hoffentlich haben sie keinen Werksreset durchgeführt und ihre 'Secure.ANDROID_ID' bleibt erhalten oder nicht 'null'. (Siehe http://developer.android.com/about/dashboards/index.html )

Wenn alle Stricke reißen:

Wenn alles andere fehlschlägt, wenn der Benutzer weniger als API 9 (niedriger als Gingerbread) hat, sein Gerät zurückgesetzt hat oder 'Secure.ANDROID_ID' 'null' zurückgibt, basiert die zurückgegebene ID einfach ausschließlich auf seinen Android-Geräteinformationen. Hier können Kollisionen auftreten.

Änderungen:

  • Das Entfernen von 'Android.SECURE_ID' aufgrund von Werksresets kann dazu führen, dass sich der Wert ändert
  • Der zu ändernde Code wurde in der API bearbeitet
  • Das Pseudo wurde geändert

Bitte schauen Sie sich die folgende Methode an:

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

Neu (für Apps mit Anzeigen UND Google Play Services):

Über die Google Play-Entwicklerkonsole:

Ab dem 1. August 2014 schreibt die Google Play Developer Program Policy vor, dass alle neuen App-Uploads und -Updates die Werbe-ID anstelle anderer dauerhafter Kennungen für Werbezwecke verwenden müssen. Erfahren Sie mehr

Implementierung :

Genehmigung:

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

Code:

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

Quelle / Dokumente:

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

Wichtig:

Es ist beabsichtigt, dass die Werbe-ID die vorhandene Verwendung anderer Kennungen für Werbezwecke (z. B. die Verwendung von ANDROID_ID in Settings.Secure) vollständig ersetzt, wenn Google Play Services verfügbar ist. Fälle, in denen Google Play Services nicht verfügbar ist, werden durch eine GooglePlayServicesNotAvailableException angezeigt, die von getAdvertisingIdInfo () ausgelöst wird.

Warnung, Benutzer können zurücksetzen:

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

Ich habe versucht, auf jeden Link zu verweisen, von dem ich Informationen genommen habe. Wenn Sie fehlen und aufgenommen werden müssen, kommentieren Sie bitte!

Google Player Services InstanceID

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

Jared Burrows
quelle
Aber würde sich die BuildKlasse beim Betriebssystem-Update nicht ändern? Vor allem, wenn die API aktualisiert wurde? Wenn ja, wie garantieren Sie, dass dies einzigartig ist? (Apropos Methode, die Sie geschrieben haben)
LuckyMe
2
Ich habe Ihre Methode in meiner App zum Senden von Kommentaren verwendet. Ich habe schlechte Neuigkeiten. Leider ist PsuedoID nicht vollständig eindeutig. Mein Server hat mehr als 100 für 5 ID und mehr als 30 für fast 30 ID aufgezeichnet. Die am häufigsten wiederholten IDs sind 'ffffffff-fc8f-6093-ffff-ffffd8' (159 Datensatz) und 'ffffffff-fe99-b334-ffff-ffffef' (154 Mal). Auch aufgrund von Zeit und Kommentaren ist es offensichtlich, dass es verschiedene Völker gibt. Die Gesamtzahl der bisherigen Datensätze beträgt 10.000. Bitte lassen Sie mich wissen, warum dies passiert ist. Panzer.
Hojjat Reyhane
1
Ich habe das vor mehr als 1,5 Jahren geschrieben. Ich bin mir nicht sicher, warum es für Sie nicht einzigartig ist. Sie können die Werbe-ID ausprobieren. Wenn nicht, können Sie Ihre eigene Lösung finden.
Jared Burrows
2
Ich würde mich sehr freuen, wenn Sie die Frage durchgehen und Ihre Gedanken dazu
äußern
1
@ user1587329 Vielen Dank. Ich versuche dies für alle auf dem neuesten Stand zu halten. Diese Frage ist schwierig, wenn es um Hardware oder Software sowie plattformübergreifende Fragen geht.
Jared Burrows
340

Wie Dave Webb erwähnt, enthält der Android Developer Blog einen Artikel , der dies behandelt. Ihre bevorzugte Lösung besteht darin, App-Installationen anstelle von Geräten zu verfolgen. Dies funktioniert in den meisten Anwendungsfällen gut. Der Blog-Beitrag zeigt Ihnen den erforderlichen Code, damit dies funktioniert, und ich empfehle Ihnen, ihn zu überprüfen.

In dem Blogbeitrag werden jedoch Lösungen erläutert, wenn Sie eine Gerätekennung anstelle einer App-Installationskennung benötigen. Ich habe mit jemandem bei Google gesprochen, um zusätzliche Informationen zu einigen Punkten zu erhalten, falls Sie dies tun müssen. Folgendes habe ich über Gerätekennungen herausgefunden, die im oben genannten Blog-Beitrag NICHT erwähnt werden:

  • ANDROID_ID ist die bevorzugte Gerätekennung. ANDROID_ID ist auf Versionen von Android <= 2.1 oder> = 2.3 absolut zuverlässig. Nur 2.2 hat die in der Post genannten Probleme.
  • Mehrere Geräte mehrerer Hersteller sind vom ANDROID_ID-Fehler in 2.2 betroffen.
  • Soweit ich feststellen konnte, haben alle betroffenen Geräte dieselbe ANDROID_ID , nämlich 9774d56d682e549c . Dies ist übrigens auch die gleiche Geräte-ID, die vom Emulator gemeldet wurde.
  • Google glaubt, dass OEMs das Problem für viele oder die meisten ihrer Geräte behoben haben, aber ich konnte überprüfen, dass es zumindest ab Anfang April 2011 immer noch recht einfach ist, Geräte mit der defekten ANDROID_ID zu finden.

Basierend auf den Empfehlungen von Google habe ich eine Klasse implementiert, die für jedes Gerät eine eindeutige UUID generiert. Dabei wird ANDROID_ID als Startwert verwendet, wobei bei Bedarf auf TelephonyManager.getDeviceId () zurückgegriffen wird. Wenn dies fehlschlägt, wird auf eine zufällig generierte eindeutige UUID zurückgegriffen Dies bleibt auch nach einem Neustart der App bestehen (jedoch nicht nach einer Neuinstallation der App).

Beachten Sie, dass für Geräte , die auf der Geräte - ID zu Rückfall haben, die eindeutige ID WIRD über Fabrik setzt bestehen bleiben. Dies ist etwas zu beachten. Wenn Sie sicherstellen müssen, dass durch einen Werksreset Ihre eindeutige ID zurückgesetzt wird, sollten Sie möglicherweise direkt auf die zufällige UUID anstelle der Geräte-ID zurückgreifen.

Auch dieser Code bezieht sich auf eine Geräte-ID und nicht auf eine App-Installations-ID. In den meisten Situationen ist eine App-Installations-ID wahrscheinlich das, wonach Sie suchen. Wenn Sie jedoch eine Geräte-ID benötigen, funktioniert der folgende Code wahrscheinlich für Sie.

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;
    }
}
emmby
quelle
6
Sollten Sie die verschiedenen IDs nicht so hashen, dass sie alle gleich groß sind? Außerdem sollten Sie die Geräte-ID hashen, um nicht versehentlich private Informationen preiszugeben.
Steve Pomeroy
2
Gute Punkte, Steve. Ich habe den Code aktualisiert, um immer eine UUID zurückzugeben. Dies stellt sicher, dass a) die generierten IDs immer dieselbe Größe haben und b) die Android- und Geräte-IDs vor der Rückgabe gehasht werden, um zu vermeiden, dass versehentlich persönliche Informationen preisgegeben werden. Ich habe auch die Beschreibung aktualisiert, um festzustellen, dass die Geräte-ID auch nach dem Zurücksetzen auf die Werkseinstellungen erhalten bleibt und dies für einige Benutzer möglicherweise nicht wünschenswert ist.
Emmby
1
Ich glaube du bist falsch; Die bevorzugte Lösung besteht darin, Installationen zu verfolgen, nicht Gerätekennungen. Ihr Code ist wesentlich länger und komplexer als der im Blog-Beitrag und es ist mir nicht klar, dass er einen Mehrwert bietet.
Tim Bray
7
Gut, ich habe den Kommentar aktualisiert, um den Benutzern dringend zu empfehlen, App-Installations-IDs anstelle von Geräte-IDs zu verwenden. Ich denke jedoch, dass diese Lösung für Personen, die ein Gerät anstelle einer Installations-ID benötigen, immer noch wertvoll ist.
Emmby
8
ANDROID_ID kann sich beim Zurücksetzen auf die Werkseinstellungen ändern, sodass auch keine Geräte identifiziert werden können
Samuel,
180

Hier ist der Code, den Reto Meier in der diesjährigen Google I / O- Präsentation verwendet hat, um eine eindeutige ID für den Nutzer zu erhalten:

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

Wenn Sie dies mit einer Sicherungsstrategie koppeln, um Einstellungen an die Cloud zu senden (ebenfalls in Retos Vortrag beschrieben) , sollten Sie eine ID haben, die an einen Benutzer gebunden ist und nach dem Löschen oder sogar Ersetzen des Geräts erhalten bleibt. Ich plane, diese zu verwenden in der Analytik in Zukunft (mit anderen Worten, ich habe das noch nicht getan :).

Anthony Nolan
quelle
Ich habe die Methode von @Lenn Dolling verwendet, wobei die aktuelle Zeit für eine eindeutige ID angehängt wurde. Dies scheint jedoch einfacher und zuverlässiger zu sein. Vielen Dank an Reto Meier und Antony Nolan
Gökhan Barış Aker
Es ist großartig, aber was ist mit gerooteten Geräten? Sie können darauf zugreifen und die UID leicht in eine andere ändern.
Tasomaniac
3
Eine großartige Option, wenn Sie die eindeutige ID nicht benötigen, um nach einer Deinstallation und Neuinstallation bestehen zu bleiben (z. B. Werbeveranstaltung / Spiel, bei dem Sie drei Gewinnchancen erhalten, Punkt).
Kyle Clegg
2
Die Meier-Präsentation basiert auf der Verwendung des Android Backup Managers, was wiederum davon abhängt, ob der Benutzer diese Funktion aktiviert. Dies ist in Ordnung für App-Benutzereinstellungen (Meiers Verwendung), da der Benutzer diese Option einfach nicht sichern kann, wenn er diese Option nicht ausgewählt hat. Bei der ursprünglichen Frage geht es jedoch darum, eine eindeutige ID für das Gerät zu generieren. Diese ID wird pro App und nicht einmal pro Installation generiert, geschweige denn pro Gerät. Da der Benutzer die Sicherungsoption auswählt, kann sie über den Benutzer hinaus verwendet werden Präferenzen (z. B. für eine zeitlich begrenzte Testversion) sind begrenzt.
Carl
12
Dies funktioniert nicht bei einer Deinstallation oder Löschung von Daten.
John Shelley
106

Sie können auch die MAC-Adresse des Wi-Fi-Adapters berücksichtigen. So abgerufen:

WifiManager wm = (WifiManager)Ctxt.getSystemService(Context.WIFI_SERVICE);
return wm.getConnectionInfo().getMacAddress();

Erfordert die Erlaubnis android.permission.ACCESS_WIFI_STATEim Manifest.

Wird als verfügbar gemeldet, auch wenn keine Wi-Fi-Verbindung besteht. Wenn Joe aus der obigen Antwort diesen auf seinen vielen Geräten ausprobiert, wäre das schön.

Auf einigen Geräten ist es nicht verfügbar, wenn Wi-Fi ausgeschaltet ist.

HINWEIS: Ab Android 6.x wird eine konsistente gefälschte Mac-Adresse zurückgegeben:02:00:00:00:00:00

Seva Alekseyev
quelle
8
Dies erforderlichandroid.permission.ACCESS_WIFI_STATE
ohhorob
5
Ich denke, Sie werden feststellen, dass es nicht verfügbar ist, wenn WiFi ausgeschaltet ist, auf so ziemlich allen Android-Geräten. Durch Deaktivieren von WiFi wird das Gerät auf Kernel-Ebene entfernt.
Chrisdowney
12
@ Sanandrea - seien wir ehrlich, auf einem gerooteten Gerät kann ALLES gefälscht werden.
ocodo
5
Der Zugriff auf die WLAN-MAC-Adresse wurde auf Android M blockiert: stackoverflow.com/questions/31329733/…
Breez
6
Von Android 6.x gibt es konsistente gefälschte Mac-Adresse zurück:02:00:00:00:00:00
Behrouz.M
87

Es gibt ziemlich nützliche Informationen hier .

Es werden fünf verschiedene ID-Typen behandelt:

  1. IMEI (nur für Android-Geräte mit Telefongebrauch; Bedürfnisse android.permission.READ_PHONE_STATE)
  2. Pseudo-eindeutige ID (für alle Android-Geräte)
  3. Android ID (kann null sein, kann sich beim Zurücksetzen auf die Werkseinstellungen ändern, kann auf einem gerooteten Telefon geändert werden)
  4. WLAN MAC Adresszeichenfolge (benötigt android.permission.ACCESS_WIFI_STATE)
  5. BT MAC Adresszeichenfolge (Geräte mit Bluetooth, benötigt android.permission.BLUETOOTH)
stansult
quelle
2
Wichtiger Punkt, der weggelassen wurde (hier und im Artikel): Sie können WLAN oder BT MAC nur erhalten, wenn sie eingeschaltet sind! Ansonsten denke ich, dass der WLAN-MAC die perfekte Kennung wäre. Sie haben keine Garantie dafür, dass der Benutzer jemals sein WLAN einschalten wird, und ich halte es nicht für "angemessen", es selbst einzuschalten.
Tom
1
@ Tom du liegst falsch. Sie können WLAN oder BT MAC auch dann noch lesen, wenn sie ausgeschaltet sind. Es gibt jedoch keine Garantie dafür, dass auf dem Gerät WLAN- oder BT-Module verfügbar sind.
Marqs
2
Insbesondere sind lokale WLAN- und Bluetooth-MAC-Adressen nicht mehr verfügbar. Die Methode getMacAddress () eines aWifiInfo-Objekts und die Methode BluetoothAdapter.getDefaultAdapter (). GetAddress () geben von nun an beide 02: 00: 00: 00: 00: 00 zurück
Sarika Kate
4
@sarikakate Es ist nur in 6.0 Marshmallow und höher wahr ... Es funktioniert immer noch wie erwartet in unter 6.0 Marshmallow.
Smeet
@Smeet Ja, Sie haben Recht. Ich habe vergessen zu erwähnen, dass es unter 6.0 funktioniert
Sarika Kate
51

Der offizielle Android-Entwickler-Blog enthält jetzt einen vollständigen Artikel zu diesem Thema: Identifizieren von App-Installationen .

BoD
quelle
4
Und der entscheidende Punkt dieses Arguments ist, dass Sie wahrscheinlich einen Fehler machen, wenn Sie versuchen, eine eindeutige ID aus der Hardware herauszuholen.
Tim Bray
3
Und wenn Sie zulassen, dass Ihre Gerätesperre durch einen Werksreset zurückgesetzt wird, ist Ihr Trialware-Modell so gut wie tot.
Seva Alekseyev
43

Bei Google I / O veröffentlichte Reto Meier eine solide Antwort darauf, wie dies angegangen werden sollte, um die Anforderungen der meisten Entwickler zu erfüllen und Benutzer über Installationen hinweg zu verfolgen. Anthony Nolan zeigt die Richtung in seiner Antwort, aber ich dachte, ich würde den vollständigen Ansatz aufschreiben, damit andere leicht sehen können, wie es geht (es dauerte eine Weile, bis ich die Details herausgefunden hatte).

Mit diesem Ansatz erhalten Sie eine anonyme, sichere Benutzer-ID, die für den Benutzer auf verschiedenen Geräten (basierend auf dem primären Google-Konto) und bei Installationen dauerhaft gültig ist. Der grundlegende Ansatz besteht darin, eine zufällige Benutzer-ID zu generieren und diese in den gemeinsamen Einstellungen der Apps zu speichern. Anschließend verwenden Sie den Backup-Agenten von Google, um die mit dem Google-Konto verknüpften freigegebenen Einstellungen in der Cloud zu speichern.

Lassen Sie uns den vollständigen Ansatz durchgehen. Zunächst müssen wir mithilfe des Android-Sicherungsdienstes ein Backup für unsere SharedPreferences erstellen. Beginnen Sie mit der Registrierung Ihrer App über http://developer.android.com/google/backup/signup.html.

Google gibt Ihnen einen Sicherungsdienstschlüssel, den Sie dem Manifest hinzufügen müssen. Sie müssen der Anwendung außerdem mitteilen, dass sie den BackupAgent wie folgt verwenden soll:

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

Anschließend müssen Sie den Sicherungsagenten erstellen und ihn anweisen, den Hilfsagenten für freigegebene Einstellungen zu verwenden:

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

Um die Sicherung abzuschließen, müssen Sie in Ihrer Hauptaktivität eine Instanz von BackupManager erstellen:

BackupManager backupManager = new BackupManager(context);

Erstellen Sie abschließend eine Benutzer-ID, falls diese noch nicht vorhanden ist, und speichern Sie sie in den 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;
}

Diese Benutzer-ID bleibt jetzt installationsübergreifend erhalten, auch wenn der Benutzer das Gerät verschiebt.

Weitere Informationen zu diesem Ansatz finden Sie in Retos Vortrag .

Ausführliche Informationen zum Implementieren des Sicherungsagenten finden Sie unter Datensicherung . Ich empfehle insbesondere den Abschnitt unten zum Testen, da die Sicherung nicht sofort erfolgt. Zum Testen müssen Sie die Sicherung erzwingen.

TechnoTony
quelle
5
Führt dies nicht zu mehreren Geräten mit derselben ID, wenn ein Benutzer mehrere Geräte hat? Ein Tablet und ein Telefon zum Beispiel.
Tosa
Hierfür ist ein Mindestziel von 8 erforderlich.
halxinate
Wäre dies der bevorzugte Weg, um bei In-App-Käufen eine Verifizierungsnutzlast zu erstellen? Aus dem In-App-Abrechnungsbeispiel-Codekommentar: "Eine gute Entwickler-Nutzlast weist also folgende Merkmale auf: 1. Wenn zwei verschiedene Benutzer einen Artikel kaufen, ist die Nutzlast zwischen ihnen unterschiedlich, sodass der Kauf eines Benutzers nicht an einen anderen Benutzer wiedergegeben werden kann. 2. Die Nutzdaten müssen so sein, dass Sie sie überprüfen können, auch wenn die App nicht derjenige war, der den Kauffluss initiiert hat (damit vom Benutzer auf einem Gerät gekaufte Artikel auf anderen Geräten des Benutzers funktionieren). "
TouchBoarder
@Tosa Ich hatte genau die gleiche Frage. Aber könnten wir diese Technik nicht erneut verwenden, um IDs für virtuelle Geräte zu erstellen und diese nicht auf die gleiche Weise zu sichern? Die Geräte-ID würde nach einem Löschen oder erneuten Installieren nicht bestehen bleiben. Wenn wir jedoch eine dauerhafte Benutzer-ID haben, benötigen wir möglicherweise nicht so viel von einer Geräte-ID.
jwehrle
39

Ich denke, dies ist ein sicherer Weg, ein Skelett für einen eindeutigen Ausweis zu bauen ... probieren Sie es aus.

Pseudo-eindeutige ID, die auf allen Android-Geräten funktioniert Einige Geräte haben kein Telefon (z. B. Tablets) oder aus irgendeinem Grund möchten Sie die Berechtigung READ_PHONE_STATE nicht einschließen. Sie können weiterhin Details wie ROM-Version, Herstellername, CPU-Typ und andere Hardwaredetails lesen, die sich gut eignen, wenn Sie die ID für eine Überprüfung des Serienschlüssels oder für andere allgemeine Zwecke verwenden möchten. Die auf diese Weise berechnete ID ist nicht eindeutig: Es ist möglich, zwei Geräte mit derselben ID (basierend auf derselben Hardware und demselben ROM-Image) zu finden, aber die Änderungen in realen Anwendungen sind vernachlässigbar. Zu diesem Zweck können Sie die Build-Klasse verwenden:

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

Die meisten Build-Mitglieder sind Zeichenfolgen. Wir nehmen hier ihre Länge und transformieren sie über Modulo in eine Ziffer. Wir haben 13 solcher Ziffern und wir fügen zwei weitere vor (35) hinzu, um die gleiche Größen-ID wie die IMEI (15 Ziffern) zu haben. Es gibt andere Möglichkeiten hier sind gut, schauen Sie sich nur diese Saiten an. Gibt so etwas wie zurück 355715565309247. Es ist keine spezielle Genehmigung erforderlich, was diesen Ansatz sehr praktisch macht.


(Zusätzliche Informationen: Die oben angegebene Technik wurde aus einem Artikel über Pocket Magic kopiert .)

Lenn Dolling
quelle
7
Interessante Lösung. Es hört sich so an, als ob dies eine Situation ist, in der Sie wirklich nur all die verketteten Daten hashen sollten, anstatt zu versuchen, Ihre eigene "Hash" -Funktion zu entwickeln. Es gibt viele Fälle, in denen Kollisionen auftreten, selbst wenn wesentliche Daten vorhanden sind, die für jeden Wert unterschiedlich sind. Meine Empfehlung: Verwenden Sie eine Hash-Funktion und wandeln Sie die binären Ergebnisse in Dezimalzahlen um und kürzen Sie sie nach Bedarf. Um es richtig zu machen, sollten Sie wirklich eine UUID oder eine vollständige Hash-Zeichenfolge verwenden.
Steve Pomeroy
21
Sie sollten Ihren Quellen Ehre machen ... Dies wurde direkt aus dem folgenden Artikel herausgehoben : pocketmagic.net/
Steve Haley
8
Diese ID ist offen für Kollisionen, bei denen Sie nicht wissen, was. Es ist praktisch garantiert, dass es auf identischen Geräten desselben Netzbetreibers gleich ist.
Seva Alekseyev
7
Dies kann sich auch ändern, wenn das Gerät aktualisiert wird.
David gegeben
8
Sehr, sehr schlechte Lösung. Getestet auf zwei Nexus 5 ... Geben Sie die gleichen Nummern zurück.
Sinan Dizdarević
38

Der folgende Code gibt die Seriennummer des Geräts mithilfe einer versteckten Android-API zurück. Dieser Code funktioniert jedoch nicht auf dem Samsung Galaxy Tab, da auf diesem Gerät nicht "ro.serialno" festgelegt ist.

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

}
Roman SL
quelle
Ich habe gerade auf xda Entwickler gelesen, dass das ro.serialnoverwendet wird, um das zu generieren Settings.Secure.ANDROID_ID. Es handelt sich also grundsätzlich um unterschiedliche Darstellungen desselben Wertes.
Martin
@Martin: aber wahrscheinlich ändert sich die Seriennummer beim Zurücksetzen des Geräts nicht. Ist es nicht? Daraus wird nur ein neuer Wert für ANDROID_IDabgeleitet.
Ronnie
Eigentlich auf allen Geräten, die ich getestet habe, waren sie gleich. Oder zumindest die Hash-Werte waren gleich (aus Datenschutzgründen schreibe ich nicht die wahren Werte in die Protokolldateien).
Martin
Dieser Wert ist der gleiche wieandroid.os.Build.SERIAL
Eugeneek
android.os.Build.SERIALwird in Android O veraltet sein, siehe android-developers.googleblog.com/2017/04/…
EpicPandaForce
32

Es ist eine einfache Frage ohne einfache Antwort.

Darüber hinaus sind alle vorhandenen Antworten hier veraltet oder unzuverlässig.

Also , wenn Sie im Jahr 2020 für eine Lösung sind .

Hier sind einige Dinge zu beachten:

Alle hardwarebasierten Kennungen (SSAID, IMEI, MAC usw.) sind für Geräte von Nicht-Google (alles außer Pixel und Nexus) unzuverlässig, die mehr als 50% der aktiven Geräte weltweit ausmachen. In den offiziellen Best Practices für Android-Kennungen heißt es daher eindeutig:

Vermeiden Sie die Verwendung von Hardware- IDs wie SSAID (Android ID), IMEI, MAC-Adresse usw.

Das macht die meisten der oben genannten Antworten ungültig. Aufgrund verschiedener Android-Sicherheitsupdates erfordern einige von ihnen neuere und strengere Laufzeitberechtigungen, die vom Benutzer einfach verweigert werden können.

Als Beispiel CVE-2018-9489, das alle oben genannten WIFI-basierten Techniken betrifft.

Das macht diese Kennungen nicht nur unzuverlässig, sondern in vielen Fällen auch unzugänglich.

Also in einfacheren Worten: Verwenden Sie diese Techniken nicht .

Viele andere Antworten hier schlagen vor, das zu verwenden AdvertisingIdClient, was ebenfalls nicht kompatibel ist, da es von Natur aus nur für die Erstellung von Anzeigenprofilen verwendet werden sollte. Es ist auch in der offiziellen Referenz angegeben

Verwenden Sie eine Werbe-ID nur für Benutzerprofile oder Anwendungsfälle für Anzeigen

Es ist nicht nur für die Geräteidentifikation unzuverlässig, sondern Sie müssen auch die Privatsphäre des Nutzers in Bezug auf die Anzeigenverfolgungsrichtlinie befolgen , in der eindeutig festgelegt ist, dass der Nutzer sie jederzeit zurücksetzen oder blockieren kann.

Also benutze es auch nicht .

Da Sie nicht die gewünschte statische global eindeutige und zuverlässige Gerätekennung haben können. Die offizielle Referenz von Android schlägt vor:

Verwenden Sie nach Möglichkeit eine FirebaseInstanceId oder eine privat gespeicherte GUID für alle anderen Anwendungsfälle, mit Ausnahme der Verhinderung von Zahlungsbetrug und der Telefonie.

Es ist einzigartig für die Anwendungsinstallation auf dem Gerät. Wenn der Benutzer die App deinstalliert, wird sie gelöscht, ist also nicht 100% zuverlässig, aber das nächstbeste.

So verwenden Sie FirebaseInstanceIddas Add neueste Firebase-Messaging - Abhängigkeit in Ihr gradle

implementation 'com.google.firebase:firebase-messaging:20.2.0'

Und verwenden Sie den folgenden Code in einem Hintergrund-Thread:

String reliableIdentifier = FirebaseInstanceId.getInstance().getId();

Wenn Sie die Geräteidentifikation auf Ihrem Remote-Server speichern müssen, speichern Sie sie nicht wie sie ist (einfacher Text), sondern einen Hash mit Salz .

Heutzutage ist dies nicht nur eine bewährte Methode , sondern Sie müssen dies auch gesetzlich gemäß den DSGVO-Kennungen und ähnlichen Vorschriften tun .

Nikita Kurtin
quelle
3
Im Moment ist dies die beste Antwort, und der erste Satz ist die beste Zusammenfassung: "Es ist eine einfache Frage ohne eine einfache Antwort - liebe es einfach.
b2mob
Sie müssen den Kommentar "außer zur Verhinderung von Zahlungsbetrug und Telefonie" ohne Antwort darauf, wie dieser Anwendungsfall angegangen werden soll, zu schätzen wissen.
Eran Boudjnah
@EranBoudjnah Das Zitat aus der offiziellen Referenz, die in der Antwort verlinkt ist. Ich kann versuchen, diesen Anwendungsfall anzusprechen, aber da er nicht spezifisch für die OP-Frage ist, sollte er gemäß der Richtlinie für den Stapelüberlauf in einer separaten speziellen Frage durchgeführt werden.
Nikita Kurtin
Ich sage nur, dass die Antwort unvollständig ist. Aber ich bin mir bewusst, dass es nicht deine Schuld ist, da dies ein Zitat ist.
Eran Boudjnah
1
@ M.UsmanKhan, die Antwort ist gleich danach geschrieben: " Heute ist es nicht nur eine bewährte Methode, Sie müssen es tatsächlich gesetzlich gemäß den DSGVO-Kennungen und ähnlichen Vorschriften tun. "
Nikita Kurtin
27

Mit dem folgenden Code können Sie die eindeutige Geräte-ID eines Android-Betriebssystemgeräts als Zeichenfolge abrufen.

deviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 
Mohit Kanada
quelle
21

Ein serielles Feld wurde der BuildKlasse in API Level 9 (Android 2.3 - Gingerbread) hinzugefügt . Die Dokumentation besagt, dass es sich um die Hardware-Seriennummer handelt. Daher sollte es eindeutig sein, wenn es auf dem Gerät vorhanden ist.

Ich weiß nicht, ob es tatsächlich von allen Geräten mit API-Level> = 9 unterstützt wird (= nicht null).

rony l
quelle
2
Leider ist es "unbekannt".
m0skit0
18

Eines werde ich hinzufügen - ich habe eine dieser einzigartigen Situationen.

Verwenden von:

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

Es stellt sich heraus, dass mein Viewsonic G Tablet zwar eine Geräte-ID meldet, die nicht Null ist, aber jedes einzelne G Tablet dieselbe Nummer meldet.

Das macht es interessant, "Pocket Empires" zu spielen, mit dem Sie sofort auf das Konto einer anderen Person zugreifen können, basierend auf der "einzigartigen" Geräte-ID.

Mein Gerät hat kein Mobilfunkgerät.

Tony Maro
quelle
Was ist die ID? ist es vielleicht 9774d56d682e549c?
Mr_and_Mrs_D
Wow, das ist so lange her, dass ich das Tablet längst weggeworfen habe. Konnte nicht sagen.
Tony Maro
Funktioniert. Außerdem ist es viel kompakter als die ID, die ich von der zufälligen UUID erhalte.
Treewallie
1
@ Treewallie funktioniert es? Können Sie dieselbe Geräte-ID von verschiedenen Apps erhalten?
Arnold Brown
@ArnoldBrown Ja. Testen Sie es unbedingt gründlich. Ich
wünsche Ihnen
16

Ausführliche Anweisungen zum Abrufen einer eindeutigen Kennung für jedes Android-Gerät, von dem aus Ihre Anwendung installiert wird, finden Sie im offiziellen Android Developers Blog-Beitrag Identifizieren von App-Installationen .

Es scheint der beste Weg zu sein, bei der Installation selbst einen zu generieren und ihn anschließend zu lesen, wenn die Anwendung neu gestartet wird.

Ich persönlich finde das akzeptabel, aber nicht ideal. Keine von Android bereitgestellte Kennung funktioniert in allen Fällen, da die meisten von den Funkzuständen des Telefons abhängen (WLAN ein / aus, Mobilfunk ein / aus, Bluetooth ein / aus). Die anderen, wie Settings.Secure.ANDROID_IDmüssen vom Hersteller implementiert werden und sind nicht garantiert einzigartig.

Das folgende Beispiel zeigt das Schreiben von Daten in eine Installationsdatei , die zusammen mit anderen Daten gespeichert werden, die die Anwendung lokal speichert.

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();
    }
}
Kevin Parker
quelle
Wenn Sie App-Installationen verfolgen möchten, ist dies perfekt. Tracking-Geräte sind jedoch viel schwieriger und es scheint keine vollständig luftdichte Lösung zu geben.
Luca Spiller
Was ist mit gerooteten Geräten? Sie können diese Installations-ID leicht ändern, oder?
Tasomaniac
Absolut. Root kann die Installations-ID ändern. Sie können mit diesem Codeblock nach root suchen
Kevin Parker
Wenn wir die Werkseinstellungen zurücksetzen, wird die Datei dann gelöscht?
Jamshid
Wenn Sie die Partition / data auf die Werkseinstellungen zurücksetzen und löschen oder formatieren, unterscheidet sich die UUID.
Kevin Parker
12

Fügen Sie den folgenden Code in die Klassendatei ein:

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

In AndroidManifest.xml hinzufügen:

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

Die eindeutige Geräte-ID eines Android-Betriebssystemgeräts als String unter Verwendung von TelephonyManagerund ANDROID_IDwird erhalten durch:

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

Ich empfehle jedoch dringend eine von Google vorgeschlagene Methode, siehe Identifizieren von App-Installationen .

Jorgesys
quelle
9

Es gibt viele verschiedene Ansätze, um diese ANDROID_IDProbleme zu umgehen ( nullmanchmal oder wenn Geräte eines bestimmten Modells immer dieselbe ID zurückgeben), mit Vor- und Nachteilen:

  • Implementierung eines benutzerdefinierten ID-Generierungsalgorithmus (basierend auf Geräteeigenschaften, die statisch sein sollen und sich nicht ändern -> wer weiß)
  • Missbrauch anderer IDs wie IMEI , Seriennummer, Wi-Fi / Bluetooth-MAC-Adresse (diese sind nicht auf allen Geräten vorhanden oder zusätzliche Berechtigungen sind erforderlich)

Ich selbst bevorzuge die Verwendung einer vorhandenen OpenUDID-Implementierung (siehe https://github.com/ylechelle/OpenUDID ) für Android (siehe https://github.com/vieux/OpenUDID ). Es ist einfach zu integrieren und nutzt die ANDROID_IDWith-Fallbacks für die oben genannten Probleme.

Andreas Klöber
quelle
8

Wie wäre es mit der IMEI . Das ist einzigartig für Android oder andere mobile Geräte.

Elzo Valugi
quelle
9
Nicht für meine Tablets, die keine IMEI haben, da sie keine Verbindung zu meinem Mobilfunkanbieter herstellen.
Brill Pappin
2
Ganz zu schweigen von CDMA-Geräten, die eine ESN anstelle einer IMEI haben.
David gegeben
@ David Gegeben gibt es CDMA mit Android?
Elzo Valugi
1
Es wird nur das tun, es ist ein Telefon :) Ein Tablet kann nicht.
Brill Pappin
3
@ElzoValugi Es ist schon "heute" und immer noch haben nicht alle Tablets SIM-Karten.
Matthew Quiros
8

So generiere ich die eindeutige ID:

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;
}
Eng.Fouad
quelle
Wenn wir ReadPhoneState in der Version 6.0 verwenden und um Laufzeitberechtigung bitten
Harsha
8

Meine zwei Cent - Hinweis: Dies ist für eine eindeutige Geräte-ID (err) - nicht für die Installation, wie im Blog der Android-Entwickler beschrieben .

Beachten Sie, dass die von @emmby bereitgestellte Lösung auf eine Anwendungs-ID zurückgreift, da die SharedPreferences nicht prozessübergreifend synchronisiert sind (siehe hier und hier ). Also habe ich das ganz vermieden.

Stattdessen habe ich die verschiedenen Strategien zum Abrufen einer (Geräte-) ID in einer Aufzählung zusammengefasst. Das Ändern der Reihenfolge der Aufzählungskonstanten wirkt sich auf die Priorität der verschiedenen Methoden zum Abrufen der ID aus. Die erste Nicht-Null-ID wird zurückgegeben oder eine Ausnahme wird ausgelöst (gemäß den guten Java-Praktiken, Null keine Bedeutung zu geben). So habe ich zum Beispiel zuerst die TELEFONIE - aber eine gute Standardauswahl wäre die 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);
        }
    }
}
Mr_and_Mrs_D
quelle
8

Hier gibt es mehr als 30 Antworten und einige sind gleich und einige sind einzigartig. Diese Antwort basiert auf wenigen dieser Antworten. Eine davon ist die Antwort von @Lenn Dolling.

Es kombiniert 3 IDs und erstellt eine 32-stellige Hex-Zeichenfolge. Es hat sehr gut für mich funktioniert.

3 IDs sind:
Pseudo-ID - Sie wird basierend auf den Spezifikationen
des physischen Geräts generiert. ANDROID_ID - Settings.Secure.ANDROID_ID
Bluetooth-Adresse - Bluetooth- Adapteradresse

Es wird ungefähr so etwas zurückgeben: 551F27C060712A72730B0A0F734064B1

Hinweis: Sie können der longIdZeichenfolge jederzeit weitere IDs hinzufügen . Zum Beispiel Seriennummer. WLAN-Adapteradresse. IMEI. Auf diese Weise machen Sie es pro Gerät einzigartiger.

@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 "";
}
ᴛʜᴇᴘᴀᴛᴇʟ
quelle
1
Das Hinzufügen der UUID zu dem longIdund speichern sie in einer Datei, wird es die einzigartige Kennung machen:String uuid = UUID.randomUUID().toString();
Mousa Alfhaily
1
Wenn alles andere fehlschlägt und der Benutzer weniger als API 9 (niedriger als Gingerbread) hat, hat er sein Telefon oder 'Secure.ANDROID_ID' zurückgesetzt. Wenn 'null' zurückgegeben wird, basiert die zurückgegebene ID einfach ausschließlich auf den Android-Geräteinformationen. Hier können Kollisionen auftreten. Versuchen Sie, DISPLAY, HOST oder ID nicht zu verwenden - diese Elemente können sich ändern. Bei Kollisionen gibt es überlappende Daten. Die Quelle: gist.github.com/pedja1/fe69e8a80ed505500caa
Mousa Alfhaily
Wenn wir versuchen, durch diese Codezeile eine eindeutige Nummer zu erhalten, können wir dann sagen, dass es sich um eine eindeutige ID handelt und dass sie niemals mit einem anderen Gerät in Konflikt steht?
Ninja
1
@Ninja Da die BLE-Mac-Adresse eindeutig ist, ist die generierte ID immer eindeutig. Wenn Sie jedoch wirklich sicher sein möchten, würde ich vorschlagen, der UUID eine hinzuzufügen longId. Ändern Sie diese eine Zeile folgendermaßen: String longId = pseudoId + androidId + btId + UUID.randomUUID().toString();Dies garantiert, dass die generierte ID eindeutig ist.
3.
@ ᴛʜᴇᴘᴀᴛᴇʟ Vielen Dank für diese große Hilfe. Eigentlich sind meine App sehr sensible Daten, deshalb muss ich mir sicher sein, deshalb bestätige ich diese Dinge nur.
Ninja
7

Eine andere Möglichkeit ist die Verwendung /sys/class/android_usb/android0/iSerialin einer App ohne jegliche Berechtigungen.

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

Um dies in Java zu tun, würde man einfach einen FileInputStream verwenden, um die iSerial-Datei zu öffnen und die Zeichen vorzulesen. Stellen Sie nur sicher, dass Sie es in einen Ausnahmebehandler einbinden, da nicht alle Geräte über diese Datei verfügen.

Es ist bekannt, dass mindestens die folgenden Geräte diese Datei weltweit lesbar haben:

  • Nexus Galaxie
  • Nexus S.
  • Motorola Xoom 3G
  • Toshiba AT300
  • HTC One V.
  • Mini MK802
  • Samsung Galaxy S II

Sie können auch meinen Blog-Beitrag sehen, in dem die Seriennummer der Android-Hardware an nicht privilegierte Apps weitergegeben wird, in dem ich diskutiere, welche anderen Dateien für Informationen verfügbar sind.

insitusec
quelle
Ich habe gerade deinen Blog-Beitrag gelesen. Ich glaube, dass dies nicht eindeutig ist: Build.SERIAL ist auch ohne Berechtigungen verfügbar und (theoretisch) eine eindeutige Hardware-Seriennummer.
Tom
1
Du hast recht. Es ist nur eine weitere Möglichkeit, Ihr Gerät zu verfolgen, und wie Sie sagten, erfordern beide Möglichkeiten keine App-Berechtigungen.
Insitusec
7

TelephonyManger.getDeviceId () Gibt die eindeutige Geräte-ID zurück, z. B. die IMEI für GSM und die MEID oder ESN für CDMA-Telefone.

final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);            
String myAndroidDeviceId = mTelephony.getDeviceId(); 

Aber ich empfehle zu verwenden:

Settings.Secure.ANDROID_ID , die die Android-ID als eindeutige 64-Bit-Hex-Zeichenfolge zurückgibt.

    String   myAndroidDeviceId = Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID); 

Manchmal gibt TelephonyManger.getDeviceId () null zurück. Um eine eindeutige ID sicherzustellen, verwenden Sie diese Methode:

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;
}
Jorgesys
quelle
Ich habe kürzlich festgestellt, dass das Gerät eines Clients vom Typ SM-G928F / Galaxy S6 edge + nur 15 statt 16 hexadezimale Ziffern für die Android-ID liefert.
Holger Jakobs
7

Für die Hardwareerkennung eines bestimmten Android-Geräts können Sie die MAC-Adressen überprüfen.

Sie können es so machen:

in AndroidManifest.xml

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

jetzt in deinem Code:

List<NetworkInterface> interfacesList = Collections.list(NetworkInterface.getNetworkInterfaces());

for (NetworkInterface interface : interfacesList) {
   // This will give you the interface MAC ADDRESS
   interface.getHardwareAddress();
}

In jedem Android-Gerät gibt es mindestens eine "wlan0" -Schnittstelle, bei der es sich um den WI-FI-Chip handelt. Dieser Code funktioniert auch, wenn WI-FI nicht aktiviert ist.

PS Es gibt eine Reihe anderer Schnittstellen, die Sie aus der Liste mit MACS erhalten. Dies kann sich jedoch zwischen den Telefonen ändern.

Ilan.b
quelle
7

Ich verwende den folgenden Code, um das zu erhalten IMEIoder Secure zu verwenden. ANDROID_IDAlternativ, wenn das Gerät nicht über Telefonfunktionen verfügt:

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);
Asaf Pinhassi
quelle
7

Genauer gesagt Settings.Secure.ANDROID_ID. Dies ist eine 64-Bit-Größe, die beim ersten Start des Geräts generiert und gespeichert wird. Es wird zurückgesetzt, wenn das Gerät gelöscht wird.

ANDROID_IDscheint eine gute Wahl für eine eindeutige Gerätekennung zu sein. Es gibt Nachteile: Erstens ist es bei Android-Versionen vor 2.2 nicht 100% zuverlässig. (“Froyo”).Außerdem gab es mindestens einen weit verbreiteten Fehler in einem beliebten Mobilteil eines großen Herstellers, bei dem jede Instanz dieselbe ANDROID_ID hat.

mumu123
quelle
1
Diese Antwort ist eine Kopie des alten Google-Blogs android-developers.googleblog.com/2011/03/… . Der Fehler ist also bereits behoben?
Sergii
7

Um die verfügbaren eindeutigen IDs in Android-Geräten zu verstehen. Verwenden Sie diesen offiziellen Leitfaden.

Best Practices für eindeutige Kennungen:

IMEI, Mac-Adressen, Instanz-ID, GUIDs, SSAID, Werbe-ID, Sicherheitsnetz-API zur Überprüfung von Geräten.

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

Waheed Nazir
quelle
6

Google Instance ID

Veröffentlicht am I / O 2015; Für Android sind Spieldienste erforderlich. 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

Es scheint, dass Google beabsichtigt, diese ID zur Identifizierung von Installationen in Android, Chrome und iOS zu verwenden.

Es identifiziert eher eine Installation als ein Gerät, aber ANDROID_ID (die akzeptierte Antwort) identifiziert jetzt auch keine Geräte mehr. Mit der ARC-Laufzeit wird für jede Installation eine neue ANDROID_ID generiert ( Details hier ), genau wie bei dieser neuen Instanz-ID. Ich denke auch, dass die meisten von uns tatsächlich nach der Identifizierung von Installationen (nicht nach Geräten) suchen.

Die Vorteile der Instanz-ID

Es scheint mir, dass Google beabsichtigt, es für diesen Zweck zu verwenden (Identifizierung Ihrer Installationen), es ist plattformübergreifend und kann für eine Reihe anderer Zwecke verwendet werden (siehe die obigen Links).

Wenn Sie GCM verwenden, müssen Sie diese Instanz-ID möglicherweise verwenden, da Sie sie benötigen, um das GCM-Token zu erhalten (das die alte GCM-Registrierungs-ID ersetzt).

Die Nachteile / Probleme

In der aktuellen Implementierung (GPS 7.5) wird die Instanz-ID von einem Server abgerufen, wenn Ihre App dies anfordert. Dies bedeutet, dass der obige Anruf ein blockierender Anruf ist - in meinen unwissenschaftlichen Tests dauert es 1-3 Sekunden, wenn das Gerät online ist, und 0,5 - 1,0 Sekunden, wenn es offline ist (vermutlich ist dies die Zeit, die es wartet, bevor es aufgibt und einen generiert zufällige ID). Dies wurde in Nordamerika auf Nexus 5 mit Android 5.1.1 und GPS 7.5 getestet.

Wenn Sie die ID für die beabsichtigten Zwecke verwenden - z. App-Authentifizierung, App-Identifikation, GCM - Ich denke, diese 1-3 Sekunden könnten ein Ärgernis sein (natürlich abhängig von Ihrer App).

Tom
quelle
1
Ein weiterer wesentlicher Nachteil von instanceID ist, dass eine neue instanceID für Sie generiert wird, wenn der Benutzer die Daten der App löscht.
Idanakav
Interessant, aber ich denke nicht, dass es die potenziellen Anwendungsfälle wirklich ändert: Die Instanz-ID wie android_id eignet sich nicht zur Identifizierung eines Geräts. Ihr Server sieht also, dass Benutzer Daten löschen, wie Benutzer Ihre App deinstallieren und neu installieren - was nicht unangemessen ist.
Tom