Come trovare il numero di serie del dispositivo Android?


115

Devo utilizzare un ID univoco per un'app Android e ho pensato che il numero di serie del dispositivo sarebbe stato un buon candidato. Come faccio a recuperare il numero di serie di un dispositivo Android nella mia app?


2
Non dimenticare di aggiungere android: name = "android.permission.READ_PHONE_STATE" al tuo manifest
Michael SIlveus,


Se desideri ottenere un ID univoco senza autorizzazioni, puoi utilizzare questa libreria per generare un ID univoco per dispositivo con Identity.getDeviceId (contesto) o un identificatore per l'installazione della tua app tramite Identity.getInstallationId (contesto) .
caw

Risposte:


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

getSystemService è un metodo della classe Activity. getDeviceID () restituirà l'MDN o MEID del dispositivo a seconda della radio utilizzata dal telefono (GSM o CDMA).

Ogni dispositivo DEVE restituire un valore univoco qui (supponendo che sia un telefono). Questo dovrebbe funzionare per qualsiasi dispositivo Android con uno slot per sim o una radio CDMA. Sei da solo con quel microonde alimentato da Android ;-)


@ Hasemam Questo non funziona per me, dando l'errore "Force Close"
Paresh Mayani

23
@ Hasemam ora funziona correttamente dopo aver aggiunto l'autorizzazione <uses-permission android: name = "android.permission.READ_PHONE_STATE"> </uses-permission> nel file androidManifest.xml.
Paresh Mayani

23
Ci sono alcuni consigli sul blog dello sviluppatore Android ufficiale sull'utilizzo di questo identificatore: android-developers.blogspot.com/2011/03/…
David Snabel-Caunt

8
a parte il microonde alimentato da Android, che ne dici di un tablet Android? :)
ajacian81

21
Questo metodo dovrebbe essere evitato, funzionerà sui telefoni ma non funzionerà sui dispositivi senza un chip telefonico (i tablet sono un esempio). Dalla 2.3 potresti usare android.os.Build.SERIAL ma dai un'occhiata al blog degli sviluppatori suggerito da @DavidCaunt.
John Mitchell

71

Come cita Dave Webb, il blog degli sviluppatori Android ha un articolo che tratta questo.

Ho parlato con qualcuno di Google per ottenere ulteriori chiarimenti su alcuni elementi. Ecco cosa ho scoperto che NON è menzionato nel post del blog di cui sopra:

  • ANDROID_ID è la soluzione preferita. ANDROID_ID è perfettamente affidabile sulle versioni di Android <= 2.1 o> = 2.3. Solo 2.2 ha i problemi menzionati nel post.
  • Diversi dispositivi di diversi produttori sono interessati dal bug ANDROID_ID nella versione 2.2.
  • Per quanto ho potuto determinare, tutti i dispositivi interessati hanno lo stesso ANDROID_ID , che è 9774d56d682e549c . Che è anche lo stesso ID dispositivo riportato dall'emulatore, btw.
  • Google ritiene che gli OEM abbiano risolto il problema per molti o la maggior parte dei loro dispositivi, ma sono stato in grado di verificare che dall'inizio di aprile 2011, almeno, è ancora abbastanza facile trovare dispositivi con ANDROID_ID rotto.

Sulla base dei consigli di Google, ho implementato una classe che genererà un UUID univoco per ogni dispositivo, utilizzando ANDROID_ID come seed ove appropriato, ricorrendo a TelephonyManager.getDeviceId () se necessario e, se ciò non riesce, ricorrendo a un UUID univoco generato in modo casuale che viene mantenuto durante i riavvii dell'app (ma non le reinstallazioni dell'app).

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
Quali autorizzazioni sono necessarie per un'app per utilizzarlo?
Dave L.

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

1
@ ef2011 è il modello di blocco ricontrollato: en.wikipedia.org/wiki/Double-checked_locking
emmby

3
Grazie per la pubblicazione. Ma cosa impedisce a qualcuno con un telefono rootato di modificare semplicemente device_id.xml per inserire un nuovo UUID di sua scelta? (cioè per aggirare un controllo di "prova gratuita") Non sarebbe meglio se la classe memorizzasse il valore in un file delle preferenze solo se dovesse ricorrere al metodo dell'ID casuale? Altrimenti, non è necessario mantenerlo tra le esecuzioni dell'applicazione; è più sicuro rigenerare.
Carlos P

1
"ANDROID_ID" è la soluzione preferita ". Tieni presente che ANDROID_ID non identifica più in modo univoco un dispositivo: 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) {
}

Questo codice restituisce il numero di serie del dispositivo utilizzando un'API Android nascosta.


7
questo mi dà solo lo stesso valore di quello che ottengo con android.os.Build.SERIAL
josephus

Mi sbaglio o questo numero di serie è lo stesso in tutti i dispositivi con una rom personalizzata specifica? Il numero di serie del mio dispositivo (nel launcher del dispositivo eclipse) mostra 01234567890ABC per un telefono con una rom personalizzata.
Peterdk

@Peterdk sul mio dispositivo con cyanogen-9 entrambi i metodi (pre andy-9 come nella risposta e quello più semplice disponibile da andy-9 in poi) riportano il s / n corretto (lo stesso dell'adesivo del produttore). Tuttavia, può dipendere dalla versione della rom personalizzata specifica. Quale rom / versione stai usando?
morgwai

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

Tuttavia, non è garantito che l'ID Android sia un identificatore univoco.


@ Paresh Mayani, è difficile dire quale potrebbe essere il problema senza guardare il codice. La mia unica ipotesi è che getContentResolverstia tornando null. Tuttavia, potrebbe valere la pena aprire una domanda e pubblicare il codice.
Anthony Forloney

4
Questo ID proviene dall'account Google associato al telefono. Il simulatore in genere non ne ha uno. Anche un vero telefono potrebbe non averne uno. Inoltre, è documentato come "può cambiare al ripristino delle impostazioni di fabbrica" ​​e può essere modificato arbitrariamente in qualsiasi momento su un telefono con root. Utilizzare a proprio rischio. Non esiste una buona alternativa: altri ID dispositivo provvisori non sono universalmente disponibili, o non univoci, o entrambi. Vedi altre risposte per il resto di questa triste storia.
Seva Alekseyev

14

C'è un ottimo post sul blog degli sviluppatori Android che ne discute .

Ne sconsiglia l'utilizzo TelephonyManager.getDeviceId()in quanto non funziona su dispositivi Android che non siano telefoni come i tablet, richiede il READ_PHONE_STATEpermesso e non funziona in modo affidabile su tutti i telefoni.

Invece potresti usare uno dei seguenti:

  • Indirizzo MAC
  • Numero di serie
  • ANDROID_ID

Il post discute i pro ei contro di ciascuno e vale la pena leggerlo in modo da poter capire quale sarebbe il migliore per il tuo uso.


+1, ciao dave, grazie per il chiarimento perché in questo momento sto sviluppando un'applicazione per tablet, dove devo avere l'ID univoco del dispositivo Android, quindi cosa devo usare per ottenere un dispositivo tablet Android univoco?
Paresh Mayani

12

Per un numero semplice che è univoco per il dispositivo e costante per tutta la sua durata (salvo un ripristino delle impostazioni di fabbrica o l'hacking), usa Settings.Secure.ANDROID_ID .

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

Per utilizzare il numero di serie del dispositivo (quello mostrato in "Impostazioni di sistema / Informazioni / Stato") se disponibile e tornare all'ID Android:

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

risposta semplice !!
faris faris

Build.SERİAL è stato ritirato in java
Eyyüp Alkış il

7

L'IMEI è buono ma funziona solo su dispositivi Android con telefono. Dovresti considerare il supporto anche per tablet o altri dispositivi Android, che non hanno un telefono.

Hai alcune alternative come: Build class members, BT MAC, WLAN MAC o anche meglio - una combinazione di tutti questi.

Ho spiegato questi dettagli in un articolo sul mio blog, vedi: http://www.pocketmagic.net/?p=1662


6

Poiché nessuna risposta qui menziona un ID perfetto, a prova di errore che sia PERSISTENTE attraverso gli aggiornamenti di sistema ed esiste in TUTTI i dispositivi (principalmente a causa del fatto che non esiste una soluzione individuale di Google), ho deciso di pubblicare un metodo che è la cosa migliore successiva combinando due degli identificatori disponibili e un controllo per scegliere tra di loro in fase di esecuzione.

Prima del codice, 3 fatti:

  1. TelephonyManager.getDeviceId()(akaIMEI) non funzionerà bene o non funzionerà affatto per dispositivi non GSM, 3G, LTE, ecc., ma restituirà sempre un ID univoco quando è presente l'hardware correlato , anche quando non è inserita alcuna SIM o anche quando non esiste uno slot SIM ( alcuni OEM lo hanno fatto).

  2. Poiché Gingerbread (Android 2.3) android.os.Build.SERIAL deve esistere su qualsiasi dispositivo che non fornisce IMEI , cioè non ha l'hardware sopra menzionato, come da politica Android.

  3. Per il fatto (2.), almeno uno di questi due identificatori univoci sarà SEMPRE presente e SERIAL può essere presente contemporaneamente a IMEI.

Nota: i fatti (1.) e (2.) sono basati su dichiarazioni di Google

SOLUZIONE

Con i fatti sopra, si può sempre avere un identificatore univoco controllando se è presente hardware associato a IMEI e tornare a SERIAL quando non lo è, poiché non è possibile verificare se il SERIAL esistente è valido. La seguente classe statica presenta 2 metodi per verificare tale presenza e utilizzare IMEI o 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;
    }


}

Consiglierei sull'uso getCleartextID_HARDCHECK. Se il riflesso non si attacca al tuo ambiente, usa getCleartextID_SIMCHECKinvece il metodo, ma prendi in considerazione che dovrebbe essere adattato alle tue specifiche esigenze di presenza SIM.

PS : tieni presente che gli OEM sono riusciti a eliminare SERIAL contro la politica di Google (più dispositivi con lo stesso SERIALE) e Google, come affermato, c'è almeno un caso noto in un grande OEM (non divulgato e non so quale marca è uno dei due, immagino Samsung).

Dichiarazione di non responsabilità : questo risponde alla domanda originale di ottenere un ID dispositivo univoco, ma l'OP ha introdotto l'ambiguità affermando di aver bisogno di un ID univoco per un'APP. Anche se per tali scenari Android_ID sarebbe migliore, NON FUNZIONERÀ dopo, ad esempio, un Titanium Backup di un'app tramite 2 diverse installazioni ROM (può anche essere la stessa ROM). La mia soluzione mantiene la persistenza che è indipendente da un flash o dal ripristino delle impostazioni di fabbrica e fallirà solo quando la manomissione IMEI o SERIAL si verifica tramite hack / mod hardware.


5

Ci sono problemi con tutti gli approcci di cui sopra. A Google i / o Reto Meier ha rilasciato una solida risposta su come affrontare questo problema che dovrebbe soddisfare le esigenze della maggior parte degli sviluppatori per monitorare gli utenti attraverso le installazioni.

Questo approccio ti darà un ID utente anonimo e sicuro che sarà persistente per l'utente su diversi dispositivi (inclusi i tablet, in base all'account Google principale) e tra le installazioni sullo stesso dispositivo. L'approccio di base è generare un ID utente casuale e memorizzarlo nelle preferenze condivise delle app. Quindi utilizzi l'agente di backup di Google per memorizzare le preferenze condivise collegate all'account Google nel cloud.

Esaminiamo l'approccio completo. Per prima cosa dobbiamo creare un backup per le nostre SharedPreferences utilizzando il servizio di backup Android. Inizia registrando la tua app tramite questo link: http://developer.android.com/google/backup/signup.html

Google ti fornirà una chiave del servizio di backup che dovrai aggiungere al manifest. È inoltre necessario indicare all'applicazione di utilizzare BackupAgent come segue:

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

Quindi è necessario creare l'agente di backup e dirgli di utilizzare l'agente di supporto per le preferenze condivise:

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

Per completare il backup è necessario creare un'istanza di BackupManager nella tua attività principale:

BackupManager backupManager = new BackupManager(context);

Infine crea un ID utente, se non esiste già, e memorizzalo in 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;
}

Questo User_ID sarà ora persistente tra le installazioni, anche se l'utente cambia dispositivo.

Per ulteriori informazioni su questo approccio, vedere il discorso di Reto qui http://www.google.com/events/io/2011/sessions/android-protips-advanced-topics-for-expert-android-app-developers.html

E per tutti i dettagli su come implementare l'agente di backup, consultare il sito per sviluppatori qui: http://developer.android.com/guide/topics/data/backup.html Consiglio in particolare la sezione in fondo sui test come fa il backup non avviene istantaneamente e quindi per testare devi forzare il backup.


2

Un altro modo è usare / sys / class / android_usb / android0 / iSerial in un'app senza autorizzazioni di sorta.

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

Per fare questo in java basta usare un FileInputStream per aprire il file iSerial e leggere i caratteri. Assicurati solo di avvolgerlo in un gestore di eccezioni perché non tutti i dispositivi hanno questo file.

Almeno i seguenti dispositivi sono noti per avere questo file leggibile in tutto il mondo:

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

Puoi anche vedere il mio post sul blog qui: http://insitusec.blogspot.com/2013/01/leaking-android-hardware-serial-number.html dove discuto di quali altri file sono disponibili per informazioni.


Grazie per aver pubblicato la tua risposta! Assicurati di leggere attentamente le FAQ sull'autopromozione . Si noti inoltre che è necessario pubblicare un disclaimer ogni volta che si collega al proprio sito / prodotto.
Andrew Barber

1

Come dice @haserman:

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

Ma è necessario includere l'autorizzazione nel file manifest:

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

1

ID dispositivo univoco del dispositivo del sistema operativo Android come stringa.

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

ma consiglio vivamente questo metodo suggerito da Google:

Identificazione delle installazioni di app


1

Build.SERIALè il modo più semplice, sebbene non del tutto affidabile in quanto può essere vuoto o talvolta restituire un valore diverso ( prova 1 , prova 2 ) rispetto a quello che puoi vedere nelle impostazioni del tuo dispositivo.

Esistono diversi modi per ottenere quel numero a seconda del produttore del dispositivo e della versione di Android, quindi ho deciso di compilare ogni possibile soluzione che ho trovato in un unico riassunto . Eccone una versione semplificata:

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

So che questa domanda è vecchia ma può essere eseguita in una riga di codice

String deviceID = Build.SERIAL;


AFAIK, questo cambierà dopo l'aggiornamento del sistema operativo del dispositivo, ad esempio da 4.4.2 a 4.4.4 o altro.
Den Drobiazko

-1

Ho trovato la classe di esempio pubblicata da @emmby sopra un ottimo punto di partenza. Ma ha un paio di difetti, come menzionato da altri poster. Il principale è che persiste l'UUID in un file XML inutilmente e quindi lo recupera sempre da questo file. Questo apre la classe a un facile hack: chiunque abbia un telefono rooted può modificare il file XML per darsi un nuovo UUID.

Ho aggiornato il codice in modo che persista solo in XML se assolutamente necessario (ovvero quando si utilizza un UUID generato in modo casuale) e ri-fattorizzato la logica come da risposta di @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;
    }

Mettere l'ID nelle preferenze condivise compromette l'obiettivo originale di ottenere un ID davvero unico. Ad esempio, se vuoi usare quell'ID come chiave per alcune restrizioni, sarai fregato quando utenti esperti eseguiranno il root di un dispositivo e avranno accesso al tuo file di preferenze condiviso. Il suo contenuto può essere copiato, il che significa ...
Eugene Wechsler

c'è anche un altro errore nella risposta di MB e nella tua .. Se usi randomUUID come deviceID e appID, funziona per tutti i dispositivi attraverso il boord, non importa se sono telefoni o no o se sono dispositivi google exp o meno.
Fred Grott

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.