webentwicklung-frage-antwort-db.com.de

Wie finde ich die Seriennummer von Android Gerät?

Ich muss eine eindeutige ID für eine Android App verwenden, und ich dachte, die Seriennummer für das Gerät wäre ein guter Kandidat. Wie kann ich die Seriennummer einer Android Gerät in meiner App?

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

getSystemService ist eine Methode aus der Activity-Klasse. getDeviceID () gibt die MDN oder MEID des Geräts zurück, je nachdem, welches Funkgerät das Telefon verwendet (GSM oder CDMA).

Jedes Gerät MUSS hier einen eindeutigen Wert zurückgeben (vorausgesetzt, es ist ein Telefon). Dies sollte für jedes Android Gerät mit einem Sim-Slot oder CDMA-Radio funktionieren. Mit dieser Android Mikrowelle bist du allein ;-)

102
haseman

Wie Dave Webb erwähnt, enthält das Android Developer Blog einen Artikel , der dies behandelt.

Ich habe mit jemandem bei Google gesprochen, um zusätzliche Informationen zu einigen Punkten zu erhalten. Folgendes habe ich entdeckt, das in dem oben genannten Blog-Beitrag NICHT erwähnt wird:

  • Android_ID ist die bevorzugte Lösung. Android_ID ist auf Versionen von Android <= 2.1 oder> = 2.3) absolut zuverlässig. Nur 2.2 weist die in der Veröffentlichung genannten Probleme auf.
  • Mehrere Geräte verschiedener Hersteller sind von dem Android_ID-Fehler in 2.2 betroffen.
  • Soweit ich feststellen konnte, haben alle betroffenen Geräte dieselbe Android_ID , also 9774d56d682e549c . Dies ist übrigens auch die gleiche Geräte-ID, die vom Emulator gemeldet wurde.
  • Google ist der Ansicht, dass OEMs das Problem für viele oder die meisten ihrer Geräte behoben haben. Ich konnte jedoch feststellen, dass es ab Anfang April 2011 immer noch recht einfach ist, Geräte mit der defekten Android_ID zu finden.

Auf der Grundlage der Empfehlungen von Google habe ich eine Klasse implementiert, die für jedes Gerät eine eindeutige UUID generiert. Dabei habe ich gegebenenfalls Android_ID als Ausgangswert verwendet und bei Bedarf auf TelephonyManager.getDeviceId () zurückgegriffen. Falls dies fehlschlägt, habe ich auf eine zufällig generierte eindeutige UUID zurückgegriffen Dies gilt auch für App-Neustarts (jedoch nicht für App-Neuinstallationen).

import Android.content.Context;
import Android.content.SharedPreferences;
import Android.provider.Settings.Secure;
import Android.telephony.TelephonyManager;

import Java.io.UnsupportedEncodingException;
import Java.util.UUID;

public class DeviceUuidFactory {

    protected static final String PREFS_FILE = "device_id.xml";
    protected static final String PREFS_DEVICE_ID = "device_id";
    protected static volatile UUID uuid;

    public DeviceUuidFactory(Context context) {
        if (uuid == null) {
            synchronized (DeviceUuidFactory.class) {
                if (uuid == null) {
                    final SharedPreferences prefs = context
                            .getSharedPreferences(PREFS_FILE, 0);
                    final String id = prefs.getString(PREFS_DEVICE_ID, null);
                    if (id != null) {
                        // Use the ids previously computed and stored in the
                        // prefs file
                        uuid = UUID.fromString(id);
                    } else {
                        final String androidId = Secure.getString(
                            context.getContentResolver(), Secure.Android_ID);
                        // Use the Android ID unless it's broken, in which case
                        // fallback on deviceId,
                        // unless it's not available, then fallback on a random
                        // number which we store to a prefs file
                        try {
                            if (!"9774d56d682e549c".equals(androidId)) {
                                uuid = UUID.nameUUIDFromBytes(androidId
                                        .getBytes("utf8"));
                            } else {
                                final String deviceId = ((TelephonyManager) 
                                        context.getSystemService(
                                            Context.TELEPHONY_SERVICE))
                                            .getDeviceId();
                                uuid = deviceId != null ? UUID
                                        .nameUUIDFromBytes(deviceId
                                                .getBytes("utf8")) : UUID
                                        .randomUUID();
                            }
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }
                        // Write the value out to the prefs file
                        prefs.edit()
                                .putString(PREFS_DEVICE_ID, uuid.toString())
                                .commit();
                    }
                }
            }
        }
    }

    /**
     * Returns a unique UUID for the current Android device. As with all UUIDs,
     * this unique ID is "very highly likely" to be unique across all Android
     * devices. Much more so than Android_ID is.
     * 
     * The UUID is generated by using Android_ID as the base key if appropriate,
     * falling back on TelephonyManager.getDeviceID() if Android_ID is known to
     * be incorrect, and finally falling back on a random UUID that's persisted
     * to SharedPreferences if getDeviceID() does not return a usable value.
     * 
     * In some rare circumstances, this ID may change. In particular, if the
     * device is factory reset a new device ID may be generated. In addition, if
     * a user upgrades their phone from certain buggy implementations of Android
     * 2.2 to a newer, non-buggy version of Android, the device ID may change.
     * Or, if a user uninstalls your app on a device that has neither a proper
     * Android ID nor a Device ID, this ID may change on reinstallation.
     * 
     * Note that if the code falls back on using TelephonyManager.getDeviceId(),
     * the resulting ID will NOT change after a factory reset. Something to be
     * aware of.
     * 
     * Works around a bug in Android 2.2 for many devices when using Android_ID
     * directly.
     * 
     * @see http://code.google.com/p/Android/issues/detail?id=10603
     * 
     * @return a UUID that may be used to uniquely identify your device for most
     *         purposes.
     */
    public UUID getDeviceUuid() {
        return uuid;
    }
}
71
emmby
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) {
}

Dieser Code gibt die Seriennummer des Geräts mit einer versteckten Android API zurück.

32
Roman SL
String deviceId = Settings.System.getString(getContentResolver(),
                                Settings.System.Android_ID);

Es kann jedoch nicht garantiert werden, dass die Android ID eine eindeutige Kennung ist.

16

Es gibt ein ausgezeichneter Beitrag im Android Entwickler-Blog diskutiert dies .

Es wird davon abgeraten, TelephonyManager.getDeviceId() zu verwenden, da dies nicht auf Android) Geräten funktioniert, die keine Telefone wie Tablets sind. READ_PHONE_STATE Berechtigung und es funktioniert nicht auf allen Handys zuverlässig.

Stattdessen können Sie eines der folgenden verwenden:

  • MAC-Adresse
  • Ordnungsnummer
  • Android_ID

In diesem Beitrag werden die Vor- und Nachteile der einzelnen Themen besprochen, und es lohnt sich, sie zu lesen, damit Sie herausfinden können, welche für Ihre Zwecke am besten geeignet sind.

14
Dave Webb

Verwenden Sie Settings.Secure.Android_ID für eine einfache Nummer, die für das Gerät eindeutig und für die gesamte Lebensdauer konstant ist (außer bei einem Factory-Reset oder Hacking).

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

Um die Seriennummer des Geräts zu verwenden (die unter "Systemeinstellungen/Info/Status" angezeigte) und auf Android ID:

String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.Android_ID);
12
Edward Brey

Die IMEI ist gut, funktioniert aber nur auf Android Geräten mit Telefon. Sie sollten in Betracht ziehen, Tablets oder andere Android Geräte zu unterstützen, die kein Telefon haben .

Sie haben einige Alternativen wie: Klassenmitglieder aufbauen, BT-MAC, WLAN-MAC oder noch besser - eine Kombination aus all diesen.

Ich habe diese Details in einem Artikel in meinem Blog erklärt, siehe: http://www.pocketmagic.net/?p=1662

7
radhoo

Da keine Antwort erfolgt, wird hier eine perfekte, ausfallsichere ID erwähnt, die sowohl PERSISTENT durch Systemaktualisierungen ist als auch in ALLEN Geräten vorhanden ist (hauptsächlich aufgrund der Tatsache, dass dort Ich habe mich entschlossen, eine Methode zu veröffentlichen, die das nächstbeste ist, indem ich zwei der verfügbaren Bezeichner kombiniert und zur Laufzeit eine Auswahl getroffen habe.

Vor dem Code 3 Fakten:

  1. TelephonyManager.getDeviceId() (akaIMEI) funktioniert nicht gut oder überhaupt nicht für Nicht-GSM-, 3G-, LTE- usw. Geräte, aber gibt bei verwandter Hardware immer eine eindeutige ID zurück ist vorhanden , auch wenn keine SIM-Karte eingelegt ist oder wenn kein SIM-Steckplatz vorhanden ist (einige OEMs haben dies getan).

  2. Seit Lebkuchen (Android 2.3) Android.os.Build.SERIAL muss auf jedem Gerät vorhanden sein, das keine IMEI bereitstellt, dh die oben genannte Hardware ist nicht vorhanden, wie in Android Richtlinie.

  3. Aufgrund der Tatsache (2.), , dass mindestens einer dieser beiden eindeutigen Bezeichner IMMER vorhanden ist und SERIAL . kann gleichzeitig mit IMEI vorhanden sein.

Hinweis: Fakt (1.) und (2.) sind basierend auf Google-Anweisungen

[~ # ~] Lösung [~ # ~]

Mit den obigen Fakten kann man immer eine eindeutige Kennung erhalten, indem man prüft, ob IMEI-gebundene Hardware vorhanden ist, und auf SERIAL zurückgreift, wenn dies nicht der Fall ist, da man nicht prüfen kann, ob die vorhandene SERIAL gültig ist. Die folgende statische Klasse enthält zwei Methoden zum Überprüfen des Vorhandenseins und Verwenden von IMEI oder SERIAL:

import Java.lang.reflect.Method;

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

public class IDManagement {

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

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

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

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

//          return Settings.Secure.Android_ID;
            return Android.os.Build.SERIAL;
        }
    }


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

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

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

//          return Settings.Secure.Android_ID;
            return Android.os.Build.SERIAL;
        }
    }


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

        int simState = telMgr.getSimState();

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

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

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

        PackageManager pm = mContext.getPackageManager();

        if (pm == null)
            return false;

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

        return retval;
    }


}

Ich würde zur Verwendung von getCleartextID_HARDCHECK. Wenn das Spiegelbild nicht in Ihrer Umgebung haftet, verwenden Sie das getCleartextID_SIMCHECK-Methode, aber berücksichtigen Sie, dass sie an Ihre spezifischen SIM-Anwesenheitsanforderungen angepasst werden sollte.

PS : Bitte beachten Sie, dass OEMs es geschafft haben, SERIAL gegen die Google-Richtlinien auszuspielen (mehrere Geräte mit derselben SERIAL) und Google, wie angegeben, gibt es mindestens einen bekannten Fall bei einem großen OEM (nicht bekannt gegeben und ich weiß auch nicht, um welche Marke es sich handelt, ich vermute, Samsung).

Haftungsausschluss : Hiermit wird die ursprüngliche Frage nach einer eindeutigen Geräte-ID beantwortet. Das OP führte jedoch zu Unklarheiten, indem es angab, dass für eine APP eine eindeutige ID erforderlich ist. Auch wenn Android_ID für solche Szenarien besser wäre, FUNKTIONIERT es NICHT, nachdem beispielsweise eine Titanium-Sicherung einer App über 2 verschiedene ROM installiert wurde (kann sogar dasselbe ROM sein). Meine Lösung wird beibehalten Persistenz, die unabhängig von einem Flash oder Factory Reset ist und nur dann fehlschlägt, wenn IMEI- oder SERIAL-Manipulationen durch Hacks/Hardware-Mods auftreten.

6
leRobot

Es gibt Probleme mit allen oben genannten Ansätzen. Bei Google i/o hat Reto Meier eine robuste Antwort auf diese Frage veröffentlicht, die den Anforderungen der meisten Entwickler entsprechen sollte, um Benutzer über Installationen hinweg zu verfolgen.

Durch diesen Ansatz erhalten Sie eine anonyme, sichere Benutzer-ID, die für den Benutzer auf verschiedenen Geräten (einschließlich Tablets, basierend auf dem primären Google-Konto) und bei Installationen auf demselben Gerät persistent 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 Sicherungsagenten von Google, um die mit dem Google-Konto verknüpften gemeinsamen Einstellungen in der Cloud zu speichern.

Lassen Sie uns den vollständigen Ansatz durchgehen. Zuerst müssen wir mithilfe des Android Backup Service ein Backup für unsere SharedPreferences erstellen. Beginnen Sie mit der Registrierung Ihrer App über diesen Link: 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 die Anwendung auch folgendermaßen anweisen, den BackupAgent zu verwenden:

<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 gemeinsame 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 schließlich 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 User_ID bleibt nun für alle Installationen erhalten, auch wenn der Benutzer das Gerät wechselt.

Weitere Informationen zu diesem Ansatz finden Sie in Retos Vortrag hier http://www.google.com/events/io/2011/sessions/Android-protips-advanced-topics-for-expert-Android-app-developers). html

Ausführliche Informationen zum Implementieren des Sicherungsagenten finden Sie auf der Entwickler-Website hier: http://developer.Android.com/guide/topics/data/backup.html Ich empfehle insbesondere den Abschnitt im Zum Testen müssen Sie die Sicherung erzwingen, da die Sicherung nicht sofort ausgeführt wird.

5
TechnoTony

Eine andere Möglichkeit ist die Verwendung von/sys/class/Android_usb/Android0/iSerial in einer App ohne jegliche Berechtigungen.

[email protected]:~$ adb Shell ls -l /sys/class/Android_usb/Android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
[email protected]:~$ 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 auszulesen. Stellen Sie nur sicher, dass Sie sie in einen Ausnahmehandler einbinden, da nicht alle Geräte über diese Datei verfügen.

Zumindest die folgenden Geräte sind dafür bekannt, dass diese Datei weltweit lesbar ist:

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

Sie können meinen Blog-Beitrag auch hier sehen: http://insitusec.blogspot.com/2013/01/leaking-Android-hardware-serial-number.html wo ich diskutiere, für welche anderen Dateien verfügbar sind Info.

2
insitusec

Eindeutige Geräte-ID von Android OS Device as String.

String deviceId;
    final TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        if (mTelephony.getDeviceId() != null){
            deviceId = mTelephony.getDeviceId(); 
         }
        else{
            deviceId = Secure.getString(getApplicationContext().getContentResolver(),   Secure.Android_ID); 
         }

ich empfehle diese von Google vorgeschlagene Methode jedoch strikt:

Identifizieren von App-Installationen

1
Jorgesys

Build.SERIAL ist der einfachste Weg, obwohl nicht ganz zuverlässig, da kann leer sein oder manchmal einen anderen Wert zurückgeben ( Beweis 1 , Beweis 2 =) als das, was Sie in den Einstellungen Ihres Geräts sehen können.

Es gibt verschiedene Möglichkeiten, um diese Nummer zu ermitteln, je nach Hersteller des Geräts und Android Version). Daher habe ich beschlossen, jede mögliche Lösung in einem einzigen Gist zu kompilieren eine vereinfachte Version davon:

public static String getSerialNumber() {
    String serialNumber;

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

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

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

    return serialNumber;
}
1
flawyte

Wie @haserman sagt:

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

Es ist jedoch erforderlich, die Berechtigung in die Manifestdatei aufzunehmen:

<uses-permission Android:name="Android.permission.READ_PHONE_STATE"/>
1
cesards

Ich weiß, dass diese Frage alt ist, aber sie kann in einer Codezeile erfolgen

String deviceID = Build.SERIAL;

0
MichaelStoddart