Comment puis-je détecter lorsqu'une application Android est en cours d'exécution dans l'émulateur?



Answers

Que diriez-vous de cette solution:

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

Je voudrais que mon code s'exécute légèrement différemment lors de l'exécution sur l'émulateur que lors de l'exécution sur un périphérique. ( Par exemple , utiliser 10.0.2.2 au lieu d'une URL publique pour s'exécuter automatiquement sur un serveur de développement.) Quel est le meilleur moyen de détecter lorsqu'une application Android s'exécute dans l'émulateur?




La solution suggérée ci-dessus pour vérifier l' ANDROID_ID fonctionné pour moi jusqu'à ce que je ANDROID_ID à jour aujourd'hui les derniers outils de SDK libérés avec Android 2.2.

Par conséquent, je suis actuellement passé à la solution suivante qui fonctionne jusqu'à présent avec le désavantage mais que vous devez mettre l'autorisation de lecture 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);
    }
} 



Quel que soit le code que vous utilisez pour faire la détection d'émulateur, je recommande fortement d'écrire des tests unitaires pour couvrir toutes les Build.FINGERPRINT , Build.HARDWARE et Build.MANUFACTURER dont vous Build.MANUFACTURER . Voici quelques exemples de tests:

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

... et voici notre code (journaux de débogage et commentaires supprimés pour la concision):

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



utilisez cette fonction:

 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;

    }



Je n'ai jamais trouvé un bon moyen de savoir si vous êtes dans l'émulateur.

mais si vous avez juste besoin de detecet si vous êtes dans un environnement de développement, vous pouvez le faire:

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

J'espère que cette aide ....




Ce code fonctionne pour moi

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

Dans le cas où ce périphérique n'a pas de carte SIM, il retaille la chaîne vide: ""

Étant donné que l'émulateur Android rétablit toujours «Android» en tant qu'opérateur de réseau, j'utilise le code ci-dessus.




Eh bien, si vous voulez être hardcore à ce sujet et ne pas utiliser des empreintes digitales qui peuvent être facilement modifiées, j'ai vu les concepts de cet article de blog effectivement codés et fonctionnels.




Puisque le moteur d'émulation sous-jacent pour Genymotion est VirtualBox et que ça ne changera pas de sitôt, j'ai trouvé le code suivant le plus fiable:

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



Cela fonctionne pour moi

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



J'ai rassemblé toutes les réponses sur cette question et suis venu avec la fonction pour détecter si Android fonctionne sur un vm / émulateur:

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

Testé sur Emulator, Genymotion et Bluestacks (1er octobre 2015).




J'ai essayé plusieurs techniques, mais je me suis contenté d'une version légèrement révisée de la vérification de Build.PRODUCT comme ci-dessous. Cela semble varier beaucoup d'émulateur à émulateur, c'est pourquoi j'ai les 3 vérifications que j'ai actuellement. Je suppose que je pourrais avoir juste vérifié si product.contains ("sdk") mais a pensé que la vérification ci-dessous était un peu plus sûre.

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

FYI - J'ai trouvé que mon Kindle Fire avait Build.BRAND = "générique", et certains des émulateurs n'avaient pas "Android" pour l'opérateur de réseau.




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

Cela devrait renvoyer true si l'application est exécutée sur un émulateur.

Ce qu'il faut faire attention, c'est de ne pas détecter tous les émulateurs car il n'y a que plusieurs émulateurs différents. C'est facile à vérifier. Nous devons nous assurer que les périphériques réels ne sont pas détectés en tant qu'émulateur.

J'ai utilisé l'application appelée " Android Device Info Share " pour vérifier cela.

Sur cette application, vous pouvez voir différents types d'informations de nombreux appareils (probablement la plupart des appareils dans le monde, si l'appareil que vous utilisez est absent de la liste, il sera ajouté automatiquement).




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



De la batterie, l'émulateur: La source d'alimentation est toujours le chargeur AC. La température est toujours 0.

Et vous pouvez utiliser Build.HOST pour enregistrer la valeur de l'hôte, un autre émulateur a une valeur d'hôte différente.




Basé sur des indices d'autres réponses, c'est probablement le moyen le plus robuste:

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




Links