[android] Come posso rilevare quando un'applicazione emulatore è in esecuzione nell'emulatore?


Answers

Che ne dici di questa soluzione:

public static boolean isEmulator() {
    return Build.FINGERPRINT.startsWith("generic")
            || Build.FINGERPRINT.startsWith("unknown")
            || Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK built for x86")
            || Build.MANUFACTURER.contains("Genymotion")
            || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
            || "google_sdk".equals(Build.PRODUCT);
}
Question

Mi piacerebbe avere il mio codice eseguito in modo leggermente diverso quando si esegue l'emulatore rispetto a quando si esegue su un dispositivo. ( Ad esempio , utilizzando 10.0.2.2 anziché un URL pubblico da eseguire automaticamente su un server di sviluppo.) Qual è il modo migliore per rilevare quando un'applicazione emulatore è in esecuzione nell'emulatore?




Ho raccolto tutte le risposte a questa domanda e ho trovato la funzione per rilevare se Android è in esecuzione su un vm / emulatore:

public boolean isvm(){


        StringBuilder deviceInfo = new StringBuilder();
        deviceInfo.append("Build.PRODUCT " +Build.PRODUCT +"\n");
        deviceInfo.append("Build.FINGERPRINT " +Build.FINGERPRINT+"\n");
        deviceInfo.append("Build.MANUFACTURER " +Build.MANUFACTURER+"\n");
        deviceInfo.append("Build.MODEL " +Build.MODEL+"\n");
        deviceInfo.append("Build.BRAND " +Build.BRAND+"\n");
        deviceInfo.append("Build.DEVICE " +Build.DEVICE+"\n");
        String info = deviceInfo.toString();


        Log.i("LOB", info);


        Boolean isvm = false;
        if(
                "google_sdk".equals(Build.PRODUCT) ||
                "sdk_google_phone_x86".equals(Build.PRODUCT) ||
                "sdk".equals(Build.PRODUCT) ||
                "sdk_x86".equals(Build.PRODUCT) ||
                "vbox86p".equals(Build.PRODUCT) ||
                Build.FINGERPRINT.contains("generic") ||
                Build.MANUFACTURER.contains("Genymotion") ||
                Build.MODEL.contains("Emulator") ||
                Build.MODEL.contains("Android SDK built for x86")
                ){
            isvm =  true;
        }


        if(Build.BRAND.contains("generic")&&Build.DEVICE.contains("generic")){
            isvm =  true;
        }

        return isvm;
    }

Testato su Emulator, Genymotion e Bluestacks (1 ottobre 2015).




Sulla base di suggerimenti da altre risposte, questo è probabilmente il modo più efficace:

isEmulator = "goldfish".equals(Build.HARDWARE)




Questo funziona per me

public boolean isEmulator() {
    return Build.MANUFACTURER.equals("unknown");
}



La soluzione sopra suggerita per verificare l' ANDROID_ID funzionato per me fino a quando non ho aggiornato oggi gli ultimi strumenti SDK rilasciati con Android 2.2.

Pertanto, attualmente sono passato alla seguente soluzione che funziona finora con lo svantaggio, tuttavia, è necessario inserire il permesso di lettura PHONE_STATE ( <uses-permission android:name="android.permission.READ_PHONE_STATE"/> )

private void checkForDebugMode() {
    ISDEBUGMODE = false; //(Secure.getString(getApplicationContext().getContentResolver(), Secure.ANDROID_ID) == null);

    TelephonyManager man = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
    if(man != null){
        String devId = man.getDeviceSoftwareVersion();
        ISDEBUGMODE = (devId == null);
    }
} 



usa questa funzione:

 public static final boolean isEmulator() {

    int rating = 0;

    if ((Build.PRODUCT.equals("sdk")) || (Build.PRODUCT.equals("google_sdk"))
            || (Build.PRODUCT.equals("sdk_x86")) || (Build.PRODUCT.equals("vbox86p"))) {
        rating++;
    }
    if ((Build.MANUFACTURER.equals("unknown")) || (Build.MANUFACTURER.equals("Genymotion"))) {
        rating++;
    }
    if ((Build.BRAND.equals("generic")) || (Build.BRAND.equals("generic_x86"))) {
        rating++;
    }
    if ((Build.DEVICE.equals("generic")) || (Build.DEVICE.equals("generic_x86")) || (Build.DEVICE.equals("vbox86p"))) {
        rating++;
    }
    if ((Build.MODEL.equals("sdk")) || (Build.MODEL.equals("google_sdk"))
            || (Build.MODEL.equals("Android SDK built for x86"))) {
        rating++;
    }
    if ((Build.HARDWARE.equals("goldfish")) || (Build.HARDWARE.equals("vbox86"))) {
        rating++;
    }
    if ((Build.FINGERPRINT.contains("generic/sdk/generic"))
            || (Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86"))
            || (Build.FINGERPRINT.contains("generic/google_sdk/generic"))
            || (Build.FINGERPRINT.contains("generic/vbox86p/vbox86p"))) {
        rating++;
    }

    return rating > 4;

    }



Indipendentemente dal codice che utilizzi per il rilevamento dell'emulatore, ti consiglio vivamente di scrivere test delle unità per coprire tutti i Build.FINGERPRINT , Build.HARDWARE e Build.MANUFACTURER cui stai dipendendo. Ecco alcuni test di esempio:

@Test
public void testIsEmulatorGenymotion() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic/vbox86p/vbox86p:4.1.1/JRO03S/eng.buildbot.20150217.102902:userdebug/test-keys",
                    "vbox86", "Genymotion")).isTrue();

    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic/vbox86p/vbox86p:5.1/LMY47D/buildbot06092001:userdebug/test-keys", "vbox86",
                    "Genymotion")).isTrue();
}

@Test
public void testIsEmulatorDefaultAndroidEmulator() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "generic_x86/sdk_google_phone_x86/generic_x86:5.0.2/LSY66H/1960483:eng/test-keys", "goldfish",
                    "unknown")).isTrue();

    assertThat(
            DeviceUtils.isRunningOnEmulator(
                    "Android/sdk_google_phone_x86_64/generic_x86_64:6.0/MASTER/2469028:userdebug/test-keys",
                    "ranchu", "unknown")).isTrue();
}

@Test
public void testIsEmulatorRealNexus5() throws Exception {
    assertThat(
            DeviceUtils.isRunningOnEmulator("google/hammerhead/hammerhead:6.0.1/MMB29K/2419427:user/release-keys",
                    "hammerhead", "LGE")).isFalse();
}

... ed ecco il nostro codice (log di debug e commenti rimossi per concisione):

public static boolean isRunningOnEmulator() {
    if (sIsRunningEmulator == null) {
        sIsRunningEmulator = isRunningOnEmulator(Build.FINGERPRINT, Build.HARDWARE, Build.MANUFACTURER);
    }

    return sIsRunningEmulator;
}

static boolean isRunningOnEmulator(String fingerprint, String hardware, String manufacturer) {
    boolean isEmulatorFingerprint = fingerprint.endsWith("test-keys");
    boolean isEmulatorManufacturer = manufacturer.equals("Genymotion")
            || manufacturer.equals("unknown");

    if (isEmulatorFingerprint && isEmulatorManufacturer) {
        return true;
    } else {
        return false;
    }
}



Questo codice funziona per me

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tm.getNetworkOperatorName();
if("Android".equals(networkOperator)) {
    // Emulator
}
else {
    // Device
}

Nel caso in cui il dispositivo non abbia la scheda SIM, ripristina la stringa vuota: ""

Poiché l'emulatore di Android ricomincia sempre "Android" come operatore di rete, utilizzo il codice precedente.




Ho provato diverse tecniche, ma ho optato per una versione leggermente riveduta del controllo di Build.PRODUCT come di seguito. Questo sembra variare un po 'dall'emulatore all'emulatore, ecco perché ho i 3 controlli che ho attualmente. Immagino che avrei potuto controllare se product.contains ("sdk"), ma ho pensato che il check in basso fosse un po 'più sicuro.

public static boolean isAndroidEmulator() {
    String model = Build.MODEL;
    Log.d(TAG, "model=" + model);
    String product = Build.PRODUCT;
    Log.d(TAG, "product=" + product);
    boolean isEmulator = false;
    if (product != null) {
        isEmulator = product.equals("sdk") || product.contains("_sdk") || product.contains("sdk_");
    }
    Log.d(TAG, "isEmulator=" + isEmulator);
    return isEmulator;
}

Cordiali saluti - Ho scoperto che il mio Kindle Fire aveva Build.BRAND = "generico", e alcuni emulatori non avevano "Android" per l'operatore di rete.




Dalla batteria, l'emulatore: la fonte di alimentazione è sempre caricabatterie CA. La temperatura è sempre 0.

Ed è possibile utilizzare Build.HOST per registrare il valore dell'host, l'emulatore differente ha un diverso valore host.




Dato che il motore di emulazione sottostante per Genymotion è VirtualBox e che non cambierà molto presto, ho trovato il seguente codice il più affidabile:

   public static boolean isGenymotion() {
        return Build.PRODUCT != null && Build.PRODUCT.contains("vbox");
}



Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")

Questo dovrebbe restituire true se l'app è in esecuzione su un emulatore.

Quello su cui dovremmo stare attenti non è la rilevazione di tutti gli emulatori perché ci sono solo diversi emulatori. È facile da controllare Dobbiamo assicurarci che i dispositivi reali non vengano rilevati come emulatore.

Ho usato l'app chiamata " Android Device Info Share " per verificarlo.

Su questa app, puoi vedere vari tipi di informazioni su molti dispositivi (probabilmente la maggior parte dei dispositivi nel mondo, se il dispositivo che stai utilizzando non è presente nell'elenco, verrà aggiunto automaticamente).




if ("sdk".equals( Build.PRODUCT )) {
 // Then you are running the app on the emulator.
        Log.w("MyAPP", "\n\n  Emulator \n\n"); 
}



Bene, se vuoi essere hardcore e non usare alcun tipo di fingerprinting che possa essere facilmente modificato, ho visto i concetti in questo post del blog in realtà codificati e funzionanti.




Non ho mai trovato un buon modo per dire se sei nell'emulatore.

ma se hai solo bisogno di rilevare se sei in un ambiente di sviluppo puoi farlo:

     if(Debug.isDebuggerConnected() ) {
        // Things to do in debug environment...
    }

Spero che questo aiuto ....




Links