¿Cómo puedo detectar cuándo se ejecuta una aplicación de Android en el emulador?

Me gustaría que mi código se ejecute de forma ligeramente diferente cuando se ejecuta en el emulador que cuando se ejecuta en un dispositivo. ( Por ejemplo , usar 10.0.2.2 en lugar de una URL pública para ejecutarse automáticamente contra un servidor de desarrollo.) ¿Cuál es la mejor forma de detectar cuándo se ejecuta una aplicación de Android en el emulador?

¿Qué tal esta solución?

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

Uno común Build.FINGERPRINT.contains("generic") ser Build.FINGERPRINT.contains("generic")

Bueno, la ID de Android no funciona para mí, actualmente estoy usando:

 "google_sdk".equals( Build.PRODUCT ); 

Según sugerencias de otras respuestas, esta es probablemente la forma más robusta:

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

¿Qué tal algo así como el código a continuación para saber si su aplicación fue firmada con la clave de depuración? no está detectando el emulador, pero podría funcionar para su propósito?

 public void onCreate Bundle b ) { super.onCreate(savedInstanceState); if ( signedWithDebugKey(this,this.getClass()) ) { blah blah blah } blah blah blah } static final String DEBUGKEY = "get the debug key from logcat after calling the function below once from the emulator"; public static boolean signedWithDebugKey(Context context, Class cls) { boolean result = false; try { ComponentName comp = new ComponentName(context, cls); PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES); Signature sigs[] = pinfo.signatures; for ( int i = 0; i < sigs.length;i++) Log.d(TAG,sigs[i].toCharsString()); if (DEBUGKEY.equals(sigs[0].toCharsString())) { result = true; Log.d(TAG,"package has been signed with the debug key"); } else { Log.d(TAG,"package signed with a key other than the debug key"); } } catch (android.content.pm.PackageManager.NameNotFoundException e) { return false; } return result; } 

Este código funciona para mí

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

En caso de que ese dispositivo no tenga una tarjeta SIM, retiene una cadena vacía: “”

Dado que el emulador de Android siempre retoma “Android” como operador de red, uso el código anterior.

Los dos siguientes están configurados en “google_sdk”:

 Build.PRODUCT Build.MODEL 

Entonces debería ser suficiente usar cualquiera de las siguientes líneas.

 "google_sdk".equals(Build.MODEL) 

o

 "google_sdk".equals(Build.PRODUCT) 

Probé varias técnicas, pero me decidí por una versión ligeramente revisada de comprobar Build.PRODUCT como se muestra a continuación. Esto parece variar bastante de emulador a emulador, es por eso que tengo las 3 comprobaciones que tengo actualmente. Supongo que podría haber comprobado si producto.contiene (“sdk”) pero pensé que el siguiente control era un poco más seguro.

 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 – Encontré que mi Kindle Fire tenía Build.BRAND = “genérico”, y algunos de los emuladores no tenían “Android” para el operador de red.

Solo busco _sdk , _sdk_ o sdk_ , o incluso solo parte de Build.PRODUCT en Build.PRODUCT :

 if(Build.PRODUCT.matches(".*_?sdk_?.*")){ //-- emulator -- }else{ //-- other device -- } 

Nunca encontré una buena manera de saber si estás en el emulador.

pero si solo necesita detectar si se encuentra en un entorno de desarrollo, puede hacer esto:

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

Espero que esto ayude….

No sé si hay mejores formas de detectar el emu, pero el emulador tendrá el archivo init.goldfish.rc en el directorio raíz.

Es el script de inicio específico del emulador, y no debería estar allí en una comstackción que no sea emulador.

Aquí está mi solución (funciona solo si ejecuta un servidor web en su máquina de depuración): he creado una tarea en segundo plano que se inicia cuando se inicia la aplicación. Busca http://10.0.2.2 y, si existe, cambia un parámetro global (IsDebug) a verdadero. Es una forma silenciosa de saber dónde se está ejecutando.

 public class CheckDebugModeTask extends AsyncTask { public static boolean IsDebug = false; public CheckDebugModeTask() { } @Override protected String doInBackground(String... params) { try { HttpParams httpParameters = new BasicHttpParams(); int timeoutConnection = 1000; HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); int timeoutSocket = 2000; HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); String url2 = "http://10.0.2.2"; HttpGet httpGet = new HttpGet(url2); DefaultHttpClient client = new DefaultHttpClient(httpParameters); HttpResponse response2 = client.execute(httpGet); if (response2 == null || response2.getEntity() == null || response2.getEntity().getContent() == null) return ""; return "Debug"; } catch (Exception e) { return ""; } } @Override protected void onPostExecute (String result) { if (result == "Debug") { CheckDebugModeTask.IsDebug = true; } } 

de la actividad principal en Crear:

 CheckDebugModeTask checkDebugMode = new CheckDebugModeTask(); checkDebugMode.execute(""); 

Bueno, si quieres ser duro al respecto y no usar ningún tipo de huella digital que pueda modificarse fácilmente, he visto los conceptos en esta publicación de blog realmente codificados y funcionando.

usa esta función:

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

Otra opción sería mirar la propiedad ro.hardware y ver si está configurada para goldfish. Desafortunadamente, no parece haber una manera fácil de hacer esto desde Java, pero es trivial desde C usando property_get () .

La solución sugerida anteriormente para verificar el ANDROID_ID funcionó para mí hasta que actualicé hoy las últimas herramientas SDK lanzadas con Android 2.2.

Por lo tanto, actualmente cambio a la siguiente solución que funciona hasta el momento con la desventaja de que debes poner el permiso de lectura 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); } } 

puedes consultar el IMEI #, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29

si recuerdo en el emulador esta devolución 0. sin embargo, no hay documentación que pueda encontrar que garantice eso. aunque el emulador no siempre devuelva 0, parece bastante seguro que un teléfono registrado no devuelva 0. qué sucedería en un dispositivo Android que no sea teléfono, o uno sin una tarjeta SIM instalada o uno que no esté actualmente registrado en el ¿red?

parece que sería una mala idea, depender de eso.

también significa que necesitarás pedir permiso para leer el estado del teléfono, lo cual es malo si aún no lo necesitas para otra cosa.

si no es así, siempre habrá un poco de algo en algún lado antes de que finalmente generes tu aplicación firmada.

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

Esto debería volverse verdadero si la aplicación se ejecuta en un emulador.

Lo que debemos tener cuidado no es detectar todos los emuladores porque solo hay varios emuladores diferentes. Es fácil de verificar Tenemos que asegurarnos de que los dispositivos reales no se detecten como un emulador.

Usé la aplicación llamada ” Compartir información del dispositivo Android ” para verificar esto.

En esta aplicación, puede ver varios tipos de información de muchos dispositivos (probablemente la mayoría de los dispositivos en el mundo, si el dispositivo que está utilizando no aparece en la lista, se agregará automáticamente).

Desde la batería, el emulador: la fuente de alimentación siempre es el cargador de CA. La temperatura siempre es 0.

Y puede usar Build.HOST para registrar el valor de host, diferentes emuladores tienen diferentes valores de host.

Todas las respuestas en un método

 static boolean checkEmulator() { try { String buildDetails = (Build.FINGERPRINT + Build.DEVICE + Build.MODEL + Build.BRAND + Build.PRODUCT + Build.MANUFACTURER + Build.HARDWARE).toLowerCase(); if (buildDetails.contains("generic") || buildDetails.contains("unknown") || buildDetails.contains("emulator") || buildDetails.contains("sdk") || buildDetails.contains("genymotion") || buildDetails.contains("x86") // this includes vbox86 || buildDetails.contains("goldfish") || buildDetails.contains("test-keys")) return true; } catch (Throwable t) {Logger.catchedError(t);} try { TelephonyManager tm = (TelephonyManager) App.context.getSystemService(Context.TELEPHONY_SERVICE); String non = tm.getNetworkOperatorName().toLowerCase(); if (non.equals("android")) return true; } catch (Throwable t) {Logger.catchedError(t);} try { if (new File ("/init.goldfish.rc").exists()) return true; } catch (Throwable t) {Logger.catchedError(t);} return false; } 

Encontré el nuevo emulador Build.HARDWARE = "ranchu" .

Referencia: https://groups.google.com/forum/#!topic/android-emulator-dev/dltBnUW_HzU

Y también encontré la forma oficial de Android para comprobar si el emulador o no. Creo que es una buena referencia para nosotros.

Desde Android API Nivel 23 [Android 6.0]

 package com.android.internal.util; /** * @hide */ public class ScreenShapeHelper { private static final boolean IS_EMULATOR = Build.HARDWARE.contains("goldfish"); } 

Tenemos ScreenShapeHelper.IS_EMULATOR para verificar si el emulador.

Desde Android API Nivel 24 [Android 7.0]

 package android.os; /** * Information about the current build, extracted from system properties. */ public class Build { /** * Whether this build was for an emulator device. * @hide */ public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1"); } 

Tenemos Build.IS_EMULATOR para verificar si el emulador.

La forma en que el oficial comprueba si el emulador no es nuevo, y tal vez no lo suficiente, las respuestas anteriores también se mencionan.

Pero esto tal vez nos muestre que el oficial proporcionará la forma de oficial para comprobar si el emulador o no.

Como se usan las formas antes mencionadas, en este momento también podemos usar las dos formas de verificar si el emulador.

Cómo acceder al paquete com.android.internal y @hide

y espera el SDK oficial abierto.

En realidad, ANDROID_ID en 2.2 siempre es igual a 9774D56D682E549C (según este hilo + mis propios experimentos).

Entonces, puedes verificar algo como esto:

 String androidID = ...; if(androidID == null || androidID.equals("9774D56D682E549C")) do stuff; 

No es el más bonito, pero cumple su función.

Esto funciona para mí

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

Coloque un archivo en el sistema de archivos del emulador; dado que el archivo no existirá en el dispositivo real, esto debería ser estable, confiable y fácil de reparar cuando se rompe.

He recostackdo todas las respuestas sobre esta pregunta y se me ocurrió una función para detectar si Android se ejecuta en un vm / emulator:

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

Probado en Emulator, Genymotion y Bluestacks (1 de octubre de 2015).

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

Todas las referencias BUILD son valores build.prop, por lo que debe tener en cuenta que si va a poner esto en el código de versión, es posible que algunos usuarios con root hayan modificado el suyo por cualquier motivo. Prácticamente no existen modificaciones que requieran el uso de una marca genérica a menos que se trate específicamente de emular el emulador.

Fingerprint es la comstackción de comstackción y la firma de comstackción del kernel. Hay comstackciones que usan generics, por lo general, directamente de Google.

En un dispositivo que se ha modificado, el IMEI también tiene la posibilidad de ser puesto a cero, por lo que no es confiable a menos que esté bloqueando los dispositivos modificados por completo.

Goldfish es la versión básica de Android de la que se extienden todos los demás dispositivos. CADA dispositivo Android tiene un init.goldfish.rc a menos que sea pirateado y eliminado por razones desconocidas.

Como el motor de emulación subyacente para Genymotion es VirtualBox y eso no va a cambiar pronto, encontré el siguiente código el más confiable:

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

Cualquiera que sea el código que use para hacer la detección del emulador, recomiendo escribir pruebas unitarias para cubrir todos los Build.FINGERPRINT , Build.HARDWARE y Build.MANUFACTURER que depende. Aquí hay algunos ejemplos de pruebas:

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

… y aquí está nuestro código (registros de depuración y comentarios eliminados por concisión):

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

Al revisar las respuestas, ninguna de ellas funcionó al usar los emuladores LeapDroid, Droid4x o Andy,

Lo que funciona en todos los casos es el siguiente:

  private static String getSystemProperty(String name) throws Exception { Class systemPropertyClazz = Class.forName("android.os.SystemProperties"); return (String) systemPropertyClazz.getMethod("get", new Class[]{String.class}).invoke(systemPropertyClazz, new Object[]{name}); } public boolean isEmulator() { boolean goldfish = getSystemProperty("ro.hardware").contains("goldfish"); boolean emu = getSystemProperty("ro.kernel.qemu").length() > 0; boolean sdk = getSystemProperty("ro.product.model").equals("sdk"); return goldfish || emu || sdk; }