Jak znaleźć numer seryjny urządzenia z systemem Android?


115

Muszę używać unikalnego identyfikatora aplikacji na Androida i pomyślałem, że numer seryjny urządzenia będzie dobrym kandydatem. Jak odzyskać numer seryjny urządzenia z systemem Android w mojej aplikacji?


2
Nie zapomnij dodać android: name = "android.permission.READ_PHONE_STATE" do swojego manifestu
Michael SIlveus


Jeśli chcesz uzyskać unikatowy identyfikator bez żadnych uprawnień, możesz użyć tej biblioteki do wygenerowania unikalnego identyfikatora dla każdego urządzenia za pomocą Identity.getDeviceId (kontekst) lub identyfikatora instalacji aplikacji za pośrednictwem Identity.getInstallationId (kontekst) .
krakaj

Odpowiedzi:


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

getSystemService to metoda z klasy Activity. getDeviceID () zwróci MDN lub MEID urządzenia w zależności od tego, jakiego radia używa telefon (GSM lub CDMA).

Każde urządzenie MUSI zwrócić tutaj unikalną wartość (zakładając, że jest to telefon). To powinno działać na każdym urządzeniu z Androidem z gniazdem karty SIM lub radiem CDMA. Dzięki tej kuchence mikrofalowej z systemem Android jesteś sam ;-)


@Hasemam To nie działa dla mnie, wyświetlając błąd „Wymuś zamknięcie”
Paresh Mayani

23
@Hasemam działa teraz dobrze po dodaniu uprawnienia <uses-Permissions android: name = "android.permission.READ_PHONE_STATE"> </uses-permission> w pliku androidManifest.xml.
Paresh Mayani

23
Na oficjalnym blogu programistów Androida znajduje się kilka porad dotyczących używania tego identyfikatora: android-developers.blogspot.com/2011/03/…
David Snabel-Caunt

8
Oprócz kuchenki mikrofalowej z systemem Android, co z tabletem z systemem Android? :)
ajacian81

21
Tej metody należy unikać, będzie działać na telefonach, ale nie będzie działać na urządzeniach bez chipa telefonicznego (przykładem są tablety). Od 2.3 można było używać android.os.Build.SERIAL, ale sprawdź blog programistów, który zasugerował @DavidCaunt.
John Mitchell

71

Jak wspomina Dave Webb, na blogu programistów Androida znajduje się artykuł na ten temat.

Rozmawiałem z kimś w Google, aby uzyskać dodatkowe wyjaśnienia dotyczące kilku kwestii. Oto, co odkryłem, a NIE zostało wspomniane we wspomnianym poście na blogu:

  • ANDROID_ID jest preferowanym rozwiązaniem. ANDROID_ID jest całkowicie niezawodny w wersjach Androida <= 2.1 lub> = 2.3. Tylko 2.2 ma problemy wymienione w poście.
  • Błąd ANDROID_ID w wersji 2.2 dotyczy kilku urządzeń różnych producentów.
  • O ile udało mi się ustalić, wszystkie urządzenia, których dotyczy problem, mają ten sam ANDROID_ID , czyli 9774d56d682e549c . Tak przy okazji, jest to ten sam identyfikator urządzenia zgłoszony przez emulator.
  • Google uważa, że ​​producenci OEM załatali problem dla wielu lub większości swoich urządzeń, ale udało mi się zweryfikować, że przynajmniej na początku kwietnia 2011 r. Nadal dość łatwo jest znaleźć urządzenia z uszkodzonym ANDROID_ID.

Opierając się na zaleceniach Google, zaimplementowałem klasę, która będzie generować unikalny UUID dla każdego urządzenia, używając ANDROID_ID jako zarodka tam, gdzie to konieczne, w razie potrzeby powracając do TelephonyManager.getDeviceId (), a jeśli to się nie powiedzie, uciekając się do losowo wygenerowanego unikalnego UUID który jest utrwalany po ponownym uruchomieniu aplikacji (ale nie podczas ponownych instalacji aplikacji).

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

1
Jakie uprawnienia są wymagane, aby aplikacja mogła z tego korzystać?
Dave L.

1
<używa-pozwolenia android: name = "android.permission.READ_PHONE_STATE"> </uses-permission>
Gabrielle

1
@ ef2011 to podwójnie sprawdzony wzorzec blokowania: en.wikipedia.org/wiki/Double-checked_locking
emmby

3
Dzięki za wysłanie wiadomości. Ale co może powstrzymać kogoś z zrootowanym telefonem przed prostą edycją device_id.xml w celu wprowadzenia nowego, wybranego przez siebie UUID? (tj. w celu obejścia testu „bezpłatnej wersji próbnej”) Czy nie byłoby lepiej, gdyby klasa zapisywała wartość w pliku preferencji tylko wtedy, gdy musiałaby uciekać się do metody losowego identyfikatora? W przeciwnym razie nie ma potrzeby utrwalania go między uruchomieniami aplikacji; bezpieczniejsze jest ponowne wygenerowanie.
Carlos P

1
„ANDROID_ID” to preferowane rozwiązanie ”. Pamiętaj, że ANDROID_ID nie identyfikuje już jednoznacznie urządzenia: stackoverflow.com/a/13465373/150016
Tom

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

Ten kod zwraca numer seryjny urządzenia przy użyciu ukrytego interfejsu API systemu Android.


7
to tylko daje mi taką samą wartość jak ta, którą otrzymuję z android.os.Build.SERIAL
josephus

Czy się mylę, czy ten numer seryjny jest taki sam we wszystkich urządzeniach z określonym niestandardowym ROMem? Numer seryjny mojego urządzenia (w programie uruchamiającym urządzenie eclipse) to 01234567890ABC dla telefonu z niestandardową pamięcią ROM.
Peterdk,

@Peterdk na moim urządzeniu z cyjanem-9 obie metody (pre andy-9 jak w odpowiedzi i łatwiejsza dostępna od andy-9 on) zgłoś poprawny s / n (taki sam jak na naklejce producenta). Może to jednak zależeć od konkretnej niestandardowej wersji ROM. Jakiego romu / wersji używasz?
morgwai

16
String deviceId = Settings.System.getString(getContentResolver(),
                                Settings.System.ANDROID_ID);

Chociaż nie ma gwarancji, że identyfikator Androida będzie unikalnym identyfikatorem.


@Paresh Mayani, Trudno powiedzieć, co może być przyczyną bez spojrzenia na kod. Moje jedyne założenie jest takie, że getContentResolverwraca null. Warto jednak otworzyć pytanie i zamieścić swój kod.
Anthony Forloney

4
Ten identyfikator pochodzi z konta Google powiązanego z telefonem. Symulator zazwyczaj go nie posiada. Prawdziwy telefon też może go nie mieć. Ponadto jest udokumentowane jako „może ulec zmianie po przywróceniu ustawień fabrycznych” i można to zmienić w dowolnym momencie na zrootowanym telefonie. Używaj na własne ryzyko. Nie ma dobrej alternatywy - inne wstępne identyfikatory urządzeń albo nie są powszechnie dostępne, albo nie są unikalne, albo jedno i drugie. Zobacz inne odpowiedzi na resztę tej smutnej historii.
Seva Alekseyev

14

Na blogu programistów Androida znajduje się świetny post omawiający to .

Odradza używanie, TelephonyManager.getDeviceId()ponieważ nie działa na urządzeniach z Androidem, które nie są telefonami, takimi jak tablety, wymaga READ_PHONE_STATEpozwolenia i nie działa niezawodnie na wszystkich telefonach.

Zamiast tego możesz użyć jednego z następujących:

  • Adres Mac
  • Numer seryjny
  • ANDROID_ID

W poście omówiono zalety i wady każdego z nich i warto go przeczytać, abyś mógł ustalić, który z nich będzie najlepszy do Twojego użytku.


+1, cześć dave, dzięki za wyjaśnienie, ponieważ obecnie tworzę aplikację na tablet, w której muszę mieć unikalny identyfikator urządzenia z systemem Android, więc czego powinienem użyć, aby uzyskać unikalny tablet z systemem Android?
Paresh Mayani,

12

Aby uzyskać prosty numer, który jest unikalny dla urządzenia i niezmienny przez cały okres jego eksploatacji (z wyjątkiem przywrócenia ustawień fabrycznych lub włamań), użyj opcji Settings.Secure.ANDROID_ID .

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

Aby użyć numeru seryjnego urządzenia (tego pokazanego w „Ustawieniach systemu / Informacje / Stan”), jeśli jest dostępny, i wrócić do identyfikatora Androida:

String serialNumber = Build.SERIAL != Build.UNKNOWN ? Build.SERIAL : Secure.getString(getContentResolver(), Secure.ANDROID_ID);

prosta odpowiedź !!
faris faris

Build.SERİAL przestarzałe w java
Eyyüp Alkış

7

IMEI jest dobry, ale działa tylko na urządzeniach z Androidem z telefonem. Powinieneś rozważyć obsługę tabletów lub innych urządzeń z Androidem, które nie mają telefonu.

Masz kilka alternatyw, takich jak: Kompiluj członków klasy, BT MAC, WLAN MAC lub jeszcze lepiej - kombinacja wszystkich tych.

Wyjaśniłem te szczegóły w artykule na moim blogu, patrz: http://www.pocketmagic.net/?p=1662


6

Ponieważ żadna odpowiedź nie wspomina o idealnym, niezawodnym identyfikatorze, który jest zarówno TRWAŁY dzięki aktualizacjom systemu, jak i istnieje na WSZYSTKICH urządzeniach (głównie ze względu na brak indywidualnego rozwiązania od Google), zdecydowałem się opublikować metodę, która jest Następną najlepszą rzeczą jest połączenie dwóch dostępnych identyfikatorów i sprawdzenie, czy wybierzesz między nimi w czasie wykonywania.

Przed kodem, 3 fakty:

  1. TelephonyManager.getDeviceId()(akaIMEI) nie będzie działać dobrze lub w ogóle nie będzie działać na urządzeniach innych niż GSM, 3G, LTE itp., ale zawsze zwróci unikalny identyfikator, gdy powiązany jest sprzęt , nawet gdy nie jest włożona karta SIM lub nawet gdy nie ma gniazda SIM ( niektórzy producenci OEM to zrobili).

  2. Ponieważ Gingerbread (Android 2.3) android.os.Build.SERIAL musi istnieć na każdym urządzeniu, które nie zapewnia IMEI , tj. Nie ma wspomnianego sprzętu, zgodnie z zasadami Androida.

  3. Z uwagi na fakt (2.), co najmniej jeden z tych dwóch unikalnych identyfikatorów będzie ZAWSZE obecny , a SERIAL może być obecny w tym samym czasie co IMEI.

Uwaga: Fakty (1.) i (2.) opierają się na oświadczeniach Google

ROZWIĄZANIE

Biorąc pod uwagę powyższe fakty, zawsze można mieć unikalny identyfikator, sprawdzając, czy istnieje sprzęt powiązany z IMEI, i powrócić do SERIALU, gdy go nie ma, ponieważ nie można sprawdzić, czy istniejący SERIAL jest ważny. Poniższa klasa statyczna przedstawia 2 metody sprawdzania takiej obecności i korzystania z IMEI lub 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;
    }


}

Radziłbym używać getCleartextID_HARDCHECK. Jeśli odbicie nie trzyma się w Twoim otoczeniu, użyj getCleartextID_SIMCHECKzamiast tego metody, ale weź pod uwagę, że powinna być dostosowana do Twoich konkretnych potrzeb w zakresie obecności karty SIM.

PS : Proszę zauważyć, że producentom OEM udało się wyprowadzić błąd SERIAL z zasadami Google (wiele urządzeń z tym samym SERIALEM), a Google, jak stwierdzono, istnieje co najmniej jeden znany przypadek w przypadku dużego producenta OEM (nie ujawniono i nie wiem, która marka to też, zgaduję, Samsung).

Zastrzeżenie : To odpowiedź na pierwotne pytanie o uzyskanie unikalnego identyfikatora urządzenia, ale OP wprowadził niejednoznaczność, stwierdzając, że potrzebuje unikalnego identyfikatora dla aplikacji. Nawet jeśli w takich scenariuszach Android_ID byłby lepszy, NIE BĘDZIE DZIAŁAŁ po, powiedzmy, kopii zapasowej Titanium aplikacji poprzez 2 różne instalacje ROM (może to być nawet ten sam ROM). Moje rozwiązanie zachowuje trwałość, która jest niezależna od flashowania lub resetowania do ustawień fabrycznych i zawiedzie tylko wtedy, gdy nastąpi manipulacja IMEI lub SERIAL przez hacki / modyfikacje sprzętowe.


5

Z wszystkimi powyższymi podejściami są problemy. W Google i / o Reto Meier wydał solidną odpowiedź na to, jak podejść do tego problemu, która powinna zaspokoić potrzeby większości programistów w zakresie śledzenia użytkowników w różnych instalacjach.

Takie podejście zapewnia anonimowy, bezpieczny identyfikator użytkownika, który będzie trwały dla użytkownika na różnych urządzeniach (w tym tabletach, w oparciu o podstawowe konto Google) i podczas instalacji na tym samym urządzeniu. Podstawowym podejściem jest wygenerowanie losowego identyfikatora użytkownika i zapisanie go we wspólnych preferencjach aplikacji. Następnie korzystasz z agenta kopii zapasowych Google do przechowywania wspólnych preferencji połączonych z kontem Google w chmurze.

Przejdźmy przez pełne podejście. Najpierw musimy utworzyć kopię zapasową naszych SharedPreferences przy użyciu usługi Android Backup Service. Zacznij od rejestracji aplikacji za pomocą tego linku: http://developer.android.com/google/backup/signup.html

Google dostarczy Ci zapasowy klucz serwisowy, który musisz dodać do manifestu. Musisz także powiedzieć aplikacji, aby używała BackupAgent w następujący sposób:

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

Następnie musisz utworzyć agenta kopii zapasowych i powiedzieć mu, aby używał agenta pomocniczego dla wspólnych preferencji:

public class MyBackupAgent extends BackupAgentHelper {
    // The name of the SharedPreferences file
    static final String PREFS = "user_preferences";

    // A key to uniquely identify the set of backup data
    static final String PREFS_BACKUP_KEY = "prefs";

    // Allocate a helper and add it to the backup agent
    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this,          PREFS);
        addHelper(PREFS_BACKUP_KEY, helper);
    }
}

Aby zakończyć tworzenie kopii zapasowej, musisz utworzyć instancję BackupManager w swojej głównej aktywności:

BackupManager backupManager = new BackupManager(context);

Na koniec utwórz identyfikator użytkownika, jeśli jeszcze nie istnieje, i zapisz go w SharedPreferences:

  public static String getUserID(Context context) {
            private static String uniqueID = null;
        private static final String PREF_UNIQUE_ID = "PREF_UNIQUE_ID";
    if (uniqueID == null) {
        SharedPreferences sharedPrefs = context.getSharedPreferences(
                MyBackupAgent.PREFS, Context.MODE_PRIVATE);
        uniqueID = sharedPrefs.getString(PREF_UNIQUE_ID, null);
        if (uniqueID == null) {
            uniqueID = UUID.randomUUID().toString();
            Editor editor = sharedPrefs.edit();
            editor.putString(PREF_UNIQUE_ID, uniqueID);
            editor.commit();

            //backup the changes
            BackupManager mBackupManager = new BackupManager(context);
            mBackupManager.dataChanged();
        }
    }

    return uniqueID;
}

Ten identyfikator_użytkownika będzie teraz trwały we wszystkich instalacjach, nawet jeśli użytkownik zmieni urządzenia.

Aby uzyskać więcej informacji na temat tego podejścia, zobacz wykład Reto tutaj http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html

Aby uzyskać szczegółowe informacje o tym, jak wdrożyć agenta kopii zapasowych, odwiedź witrynę programistów tutaj: http://developer.android.com/guide/topics/data/backup.html Szczególnie polecam sekcję na dole dotyczącą testowania, ponieważ robi to kopia zapasowa nie dzieje się natychmiast, więc aby przetestować, musisz wymusić tworzenie kopii zapasowej.


2

Innym sposobem jest użycie / sys / class / android_usb / android0 / iSerial w aplikacji bez jakichkolwiek uprawnień.

user@creep:~$ adb shell ls -l /sys/class/android_usb/android0/iSerial
-rw-r--r-- root     root         4096 2013-01-10 21:08 iSerial
user@creep:~$ adb shell cat /sys/class/android_usb/android0/iSerial
0A3CXXXXXXXXXX5

Aby to zrobić w Javie, wystarczy użyć FileInputStream, aby otworzyć plik iSerial i odczytać znaki. Tylko pamiętaj, aby umieścić go w obsłudze wyjątków, ponieważ nie wszystkie urządzenia mają ten plik.

Przynajmniej następujące urządzenia są znane z tego, że ten plik jest czytelny dla wszystkich:

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

Możesz również zobaczyć mój post na blogu tutaj: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html, gdzie omawiam, jakie inne pliki są dostępne dla informacji.


Dziękujemy za przesłanie odpowiedzi! Przeczytaj uważnie często zadawane pytania dotyczące autopromocji . Należy również pamiętać, że jest to konieczne , aby umieścić disclaimer każdym razem, gdy odwołują się do swojej własnej strony / produktu.
Andrew Barber

1

Jak mówi @haserman:

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

Konieczne jest jednak uwzględnienie pozwolenia w pliku manifestu:

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

1

Unikalny identyfikator urządzenia z systemem operacyjnym Android jako ciąg.

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

ale zdecydowanie polecam tę metodę sugerowaną przez Google:

Identyfikowanie instalacji aplikacji


1

Build.SERIALto najprostszy sposób, chociaż nie do końca niezawodny, ponieważ może być pusty lub czasami zwracać inną wartość ( dowód 1 , dowód 2 ) niż to, co możesz zobaczyć w ustawieniach urządzenia.

Istnieje kilka sposobów uzyskania tego numeru w zależności od producenta urządzenia i wersji Androida, więc zdecydowałem się skompilować każde możliwe rozwiązanie, które mogłem znaleźć w jednym skrócie . Oto uproszczona wersja:

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

0

Wiem, że to pytanie jest stare, ale można to zrobić w jednej linii kodu

String deviceID = Build.SERIAL;


AFAIK, zmieni się to po aktualizacji systemu operacyjnego urządzenia, np. Z 4.4.2 do 4.4.4 lub cokolwiek innego.
Den Drobiazko

-1

Uważam, że przykładowa klasa opublikowana przez @emmby powyżej jest świetnym punktem wyjścia. Ale ma kilka wad, o których wspominają inne plakaty. Głównym z nich jest to, że niepotrzebnie utrwala identyfikator UUID w pliku XML, a następnie zawsze pobiera go z tego pliku. To otwiera klasę na łatwy hack: każdy, kto ma zrootowany telefon, może edytować plik XML, aby nadać sobie nowy identyfikator UUID.

Zaktualizowałem kod, aby zachowywał się w formacie XML tylko wtedy, gdy jest to absolutnie konieczne (np. Podczas korzystania z losowo wygenerowanego identyfikatora UUID) i ponownie rozłożyłem logikę zgodnie z odpowiedzią @Brill Pappin:

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 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) || (androidId == null) ) {
                                final String deviceId = ((TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE )).getDeviceId();

                                if (deviceId != null)
                                {
                                    uuid = UUID.nameUUIDFromBytes(deviceId.getBytes("utf8"));
                                }
                                else
                                {
                                    uuid = UUID.randomUUID();

                                    // Write the value out to the prefs file so it persists
                                    prefs.edit().putString(PREFS_DEVICE_ID, uuid.toString() ).commit();
                                }
                            }
                            else
                            {
                                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
                            } 
                        } catch (UnsupportedEncodingException e) {
                            throw new RuntimeException(e);
                        }



                    }

                }
            }
        }

    }


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

Umieszczenie id we wspólnych prefs kompromituje pierwotny cel uzyskania naprawdę unikalnego identyfikatora. Np. Jeśli chcesz użyć tego identyfikatora jako klucza do pewnych ograniczeń, będziesz miał problemy, gdy doświadczeni użytkownicy zrootują urządzenie i uzyskają dostęp do Twojego współdzielonego pliku preferencji. Jego zawartość można skopiować, co oznacza ...
Eugene Wechsler

jest jeszcze jeden błąd w odpowiedzi MB i twoim ... Jeśli używasz randomUUID jako identyfikatora urządzenia i identyfikatora aplikacji, działa to na wszystkich urządzeniach na serwerze, bez względu na to, czy są to telefony, czy nie, czy są to urządzenia Google Exp, czy nie.
Fred Grott

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.