Как определить, когда приложение Android работает в эмуляторе?

Я хотел бы, чтобы мой код выполнялся несколько иначе при работе на эмуляторе, чем при работе на устройстве. ( Например, используя 10.0.2.2 вместо общедоступного URL-адреса для автоматического запуска на сервере разработки.) Каков наилучший способ определить, когда приложение Android работает в эмуляторе?

Ответ 1

Как насчет этого решения:

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

Ответ 2

Один общий, который должен быть Build.FINGERPRINT.contains("generic")

Ответ 3

Ну Android-идентификатор не работает для меня, я в настоящее время использую:

"google_sdk".equals( Build.PRODUCT );

Ответ 4

Основываясь на подсказках из других ответов, это, вероятно, самый надежный способ:

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

Ответ 5

Как насчет кода, приведенного ниже, чтобы узнать, подписано ли ваше приложение с помощью отладочного ключа? он не обнаруживает эмулятор, но он может работать для вашей цели?

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;

} 

Ответ 6

Этот код работает для меня

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

Если у устройства нет сим-карты, он перенастраивает пустую строку: ""

Так как эмулятор Android всегда перенастраивает "Android" в качестве оператора сети, я использую код выше.

Ответ 7

Оба параметра установлены на "google_sdk":

Build.PRODUCT
Build.MODEL

Поэтому достаточно использовать одну из следующих строк.

"google_sdk".equals(Build.MODEL)

или

"google_sdk".equals(Build.PRODUCT)

Ответ 8

Я попробовал несколько методов, но остановился на слегка переработанной версии проверки Build.PRODUCT, как показано ниже. Похоже, что это немного отличается от эмулятора к эмулятору, поэтому у меня есть 3 проверки, которые у меня есть. Наверное, я мог бы просто проверить, есть ли product.contains( "sdk" ), но подумал, что чек ниже был немного безопаснее.

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 - я обнаружил, что у моего Kindle Fire был Build.BRAND = "generic", а некоторые из эмуляторов не имели "Android" для оператора сети.

Ответ 9

Google использует этот код в плагине информации об устройстве от Flutter, чтобы определить, является ли устройство эмулятором:

private boolean isEmulator() {
    return (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
        || Build.FINGERPRINT.startsWith("generic")
        || Build.FINGERPRINT.startsWith("unknown")
        || Build.HARDWARE.contains("goldfish")
        || Build.HARDWARE.contains("ranchu")
        || Build.MODEL.contains("google_sdk")
        || Build.MODEL.contains("Emulator")
        || Build.MODEL.contains("Android SDK built for x86")
        || Build.MANUFACTURER.contains("Genymotion")
        || Build.PRODUCT.contains("sdk_google")
        || Build.PRODUCT.contains("google_sdk")
        || Build.PRODUCT.contains("sdk")
        || Build.PRODUCT.contains("sdk_x86")
        || Build.PRODUCT.contains("vbox86p")
        || Build.PRODUCT.contains("emulator")
        || Build.PRODUCT.contains("simulator");
}

Ответ 10

Я просто ищу _sdk, _sdk_ или sdk_, или даже просто sdk часть в Build.PRODUCT:

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

Ответ 11

Я никогда не нашел хороший способ сказать, находитесь ли вы в эмуляторе.

но если вам просто нужно детектировать, если вы находитесь в среде разработки, вы можете сделать это:

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

Надеюсь на эту помощь....

Ответ 12

Не знаю, есть ли лучшие способы обнаружения emu, но эмулятор будет иметь файл init.goldfish.rc в корневой директории.

Это конкретный запуск эмулятора - script, и его не должно быть в сборке без эмулятора.

Ответ 13

Вот мое решение (оно работает только при запуске веб-сервера на вашем отладочном компьютере): Я создал фоновое задание, которое начинается с момента запуска приложения. Он ищет http://10.0.2.2, и если он существует, он изменяет глобальный параметр (IsDebug) на true. Это бесшумный способ узнать, где вы работаете.

public class CheckDebugModeTask extends AsyncTask<String, Void, String> {
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;
}
}

из основного действия onCreate:

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

Ответ 14

используйте эту функцию:

 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;

    }

Ответ 15

От батареи, эмулятор: Источником питания всегда является зарядное устройство переменного тока. Температура всегда равна 0.

И вы можете использовать Build.HOST для записи значения хоста, у другого эмулятора есть другое значение хоста.

Ответ 16

Ну, если вы хотите быть хардкором и не использовать какой-либо отпечаток пальца, который можно легко изменить, я видел концепции в этом сообщении в блоге фактически закодированы и работают.

Ответ 17

Другой вариант - посмотреть свойство ro.hardware и посмотреть, установлен ли его набор на золотую рыбу. К сожалению, похоже, что нет простого способа сделать это с Java, но его тривиально от C, используя property_get().

Ответ 18

Вышеупомянутое предлагаемое решение для проверки ANDROID_ID работало для меня, пока я не обновил сегодня до последних инструментов SDK, выпущенных с Android 2.2.

Поэтому я в настоящее время переключился на следующее решение, которое работает до сих пор с недостатком, однако вам нужно установить разрешение на чтение 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);
    }
} 

Ответ 19

Все ответы одним способом

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

Ответ 20

Я нашел новый эмулятор Build.HARDWARE = "ranchu".

Справка:https://groups.google.com/forum/#!topic/android-emulator-dev/dltBnUW_HzU

А также я нашел официальный способ Android проверить, является ли эмулятор или нет. Я думаю, что это хорошая ссылка для нас.

Since Android API Level 23 [Android 6.0]

package com.android.internal.util;

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

У нас есть ScreenShapeHelper.IS_EMULATOR, чтобы проверить, есть ли эмулятор.

Since Android API Level 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");

}

У нас есть Build.IS_EMULATOR, чтобы проверить, есть ли эмулятор.

Официальный способ проверить, является ли эмулятор не новым, а также, возможно, недостаточно, ответы выше также упоминается.

Но это может показать нам, что чиновник предоставит возможность чиновнику проверить, работает ли эмулятор или нет.

Как и все вышеперечисленные способы, упомянутые выше, прямо сейчас мы также можем использовать два способа проверки наличия эмулятора.

Как получить доступ к пакету com.android.internal и @hide

и дождаться официального открытия SDK.

Ответ 21

Моя рекомендация:

попробуй это с github.

Легко обнаружить эмулятор Android

  • Проверено на реальных устройствах в Device Farm (https://aws.amazon.com/device-farm/)
  • BlueStacks
  • Genymotion
  • Эмулятор Android
  • Энди 46.2.207.0
  • MEmu play
  • Nox App Player
  • Koplayer
  • ...

Как использовать с примером:

EmulatorDetector.with(this)
                .setCheckTelephony(true)
                .addPackageName("com.bluestacks")
                .setDebug(true)
                .detect(new EmulatorDetector.OnEmulatorDetectorListener() {
                    @Override
                    public void onResult(boolean isEmulator) {

                    }
                });

Ответ 22

Вы можете проверить IMEI #, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29

если я вызову на эмуляторе это возвращение 0. однако, нет никакой документации, которую я могу найти, которая гарантирует это. хотя эмулятор может не всегда возвращать 0, вполне вероятно, что зарегистрированный телефон не вернет 0. что произойдет на устройстве, не являющемся телефоном для Android, или на устройстве без установленной SIM-карты или на устройстве, которое в данный момент не зарегистрировано на сеть?

кажется, что это плохая идея, зависеть от этого.

это также означает, что вам нужно запросить разрешение на чтение состояния телефона, что плохо, если вам это не нужно для чего-то другого.

если не так, то всегда где-то переворачивается, прежде чем вы, наконец, генерируете подписанное приложение.

Ответ 23

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

Это должно возвращать true, если приложение запущено на эмуляторе.

Мы должны быть осторожны, не обнаруживаем все эмуляторы, потому что есть только несколько разных эмуляторов. Это легко проверить. Мы должны убедиться, что фактические устройства не обнаружены в качестве эмулятора.

Я использовал приложение "" Информация об устройстве Android", чтобы проверить это.

В этом приложении вы можете видеть различные виды информации многих устройств (возможно, большинство устройств в мире, если устройство, которое вы используете, отсутствует в списке, оно будет добавлено автоматически).

Ответ 24

Собственно, ANDROID_ID на 2.2 всегда равен 9774D56D682E549C (согласно этот поток + мои собственные эксперименты).

Итак, вы можете проверить что-то вроде этого:

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

Не самый красивый, но он выполняет эту работу.

Ответ 25

Это работает для меня

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

Ответ 26

Поместите файл в файловую систему эмулятора; так как файл не будет существовать на реальном устройстве, он должен быть стабильным, надежным и легко фиксироваться при его разрыве.

Ответ 27

Я собрал все ответы на этот вопрос и придумал функцию, чтобы определить, работает ли Android на 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;
    }

Протестировано на эмуляторе, Genymotion и Bluestacks (1 октября 2015 г.).

Ответ 28

Поскольку базовый эмуляционный движок для Genymotion - это VirtualBox и который не скоро изменится, я нашел следующий код самым надежным:

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

Ответ 29

Какой бы код вы ни использовали для обнаружения эмулятора, я настоятельно рекомендую писать модульные тесты для покрытия всех значений Build.FINGERPRINT, Build.HARDWARE и Build.MANUFACTURER, на которые вы в зависимости от. Вот несколько примеров тестов:

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

... и здесь наш код (отладочные журналы и комментарии удалены для краткости):

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

Ответ 30

Проверка ответов, ни одна из них не работала при использовании эмуляторов LeapDroid, Droid4x или Andy,

Что работает для всех случаев:

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