[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?




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 funziona per me

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



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.




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




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



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.




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

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




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 ....




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;

    }



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



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



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.