Надежный способ определения того, работает ли приложение Android в "BlueStacks",

Я хотел бы узнать во время выполнения внутри приложения Android, работает ли он в эмуляторе BlueStacks. Это значит, что я могу изменить способ запуска приложения при работе в BlueStacks.

BlueStacks не поддерживает multi-touch, поэтому я хочу реализовать альтернативу стандартным функциям pinch-to-zoom, которые есть в моем текущем приложении.

например.

If (appIsRunningInBlueStacks){
    mySurfaceView.enableMultiTouchAlternatives();
} else{
    mySurfaceView.enableMultiTouchFeatures();
}

Что такое надежный способ определения значения appIsRunningInBlueStacks?

EDIT Резюме ответов на комментарии к вопросу:

Бен, Тарас, спасибо за предложения. Значения Build.MODEL для BlueStacks:

  • Модель: "GT-I9100"

  • Производитель: "samsung"

  • Устройство: "GT-I9100"

  • Продукт: "GT-I9100"

Это тот же номер модели, что и Samsung Galaxy SII, поэтому было бы нецелесообразно использовать это, опасаясь, что все пользователи будут иметь SII, такие же, как на BlueStacks.

CommonsWare, приложение продолжает работать в BlueStacks даже с < uses-feature > для мультитач в манифесте. На самом деле (также отвечая на вопрос iagreen)...

packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);

... возвращает true! Этого можно ожидать, я полагаю, поскольку эмулятор убежден, что это Samsung Galaxy SII!

Поэтому мы по-прежнему не можем надежно обнаружить, работает ли приложение на BlueStacks, не бросая всех пользователей Samsung Galaxy SII в то же самое ведро. Любые другие идеи?

Ответ 1

Вы можете проверить, существует ли общая папка Bluestacks /SDCard/ окна/BstSharedFolder

    Boolean onBlueStacks()
        {
        File sharedFolder = new File(Environment
                .getExternalStorageDirectory().toString()
                + File.separatorChar
                + "windows"
                + File.separatorChar
                + "BstSharedFolder");

        if (sharedFolder.exists())
            {
            return true;
            }

        return false;
        }

Ответ 2

Моя версия BlueStacks сообщает мне Build.Model как GT-N7100.

Использование: android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER) Я получаю Bluestacks.

Ответ 3

Попробовав все предлагаемые решения, доступные в Интернете, мы обнаружили, что API-интерфейс аттестации Google SafetyNet является единственным решением для обнаружения виртуальных машин, таких как BlueStack (любая версия) и NoxPlayer.

Приложения, которые заботятся о пиратстве контента (и других проблемах безопасности), могут фильтровать свою доступность в Google Play, как фильтры Netflix в PlayStore.

Новый раздел консоли "Каталог устройств" включает в себя параметр "Исключение SafetyNet", который можно использовать для предотвращения загрузки "определенными приложениями устройств, не прошедших проверку целостности или не сертифицированных Google": корневые устройства и те, на которых запущены пользовательские ПЗУ.

Но есть ловушка, пользователь по-прежнему найдет APK из системы совместного использования или других систем распространения, поэтому клиент должен реализовать SafetyNet Attestation API на уровне приложения.

Как это работает?

SafetyNet проверяет информацию о программном и аппаратном обеспечении на устройстве, на котором установлено приложение, для создания профиля этого устройства. Затем служба пытается найти этот же профиль в списке моделей устройств, которые прошли тестирование на совместимость с Android. API также использует эту информацию о программном и аппаратном обеспечении, чтобы помочь вам оценить базовую целостность устройства, а также информацию об APK вызывающего приложения. Эта аттестация помогает вам определить, было ли подделано или не изменено конкретное устройство.

Это (простой в реализации) платный API от Google, который позволяет получать 10000 бесплатных обращений в день:\

Если кто-то заинтересован в самостоятельном обнаружении виртуальных машин, это хорошие статьи, предлагающие эвристические подходы:

Уклонение Android Runtime Analysis с помощью обнаружения песочницы

Ярость против виртуальной машины: препятствие динамическому анализу вредоносных программ для Android

Ответ 4

Может быть, уже слишком поздно, но ради других, у которых такая же проблема:

public boolean isRunningOnEmulator() {
    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)
        || Build.PRODUCT.contains("vbox86p")
        || Build.DEVICE.contains("vbox86p")
        || Build.HARDWARE.contains("vbox86");
}

Ответ 5

Основываясь на ответе г-на Реджиса, вы можете обнаружить его, когда есть общая папка. Однако в Bluestacks 4 использование file.exists() вернет только false. Это связано с тем, что общая папка не имеет разрешений (000 или ----------). Но перечисление файлов в каталоге обнаружит папку.

String path = Environment.getExternalStorageDirectory().toString();
Log.d("FILES", "Path: " + path);
File directory = new File(path);
File[] files = directory.listFiles();
for (File file : files) {
    if (file.getName().contains("windows")) {
        Log.d("FILES", "windows file exists");
    }
}

Ответ 6

Это будет уникальным.

В Bluestack нет устройства Bluetooth.

Поэтому попробуйте получить строку "Адрес Bluetooth", которая всегда "null" на Bluestack или Any emulator. Убедитесь, что вы добавили разрешение Bluetooth в манифест проекта.

BluetoothAdapter m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

 String m_bluetoothAdd = m_BluetoothAdapter.getAddress();

Ответ 7

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

  public boolean isEmulator() {
        String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
        Log.d("ares","ANDROID_ID: "+android_id);
        Log.d("ares","Build.PRODUCT: "+Build.PRODUCT); 
        boolean emulator = TextUtils.isEmpty(android_id) || "google_sdk".equals( Build.PRODUCT ) || "sdk".equals(Build.PRODUCT);            
        return emulator;
    }

Пожалуйста, проигнорируйте, если он полностью не поможет...