Reliable way of detecting whether an Android app is running in 'BlueStacks'
Asked Answered
O

7

18

I would like to ascertain at run-time inside an Android app whether it is running within the BlueStacks Android emulator. This is so I can modify the way the app runs when running inside BlueStacks.

BlueStacks does not support multi-touch so I want to implement an alternative to the standard pinch-to-zoom functionality my current app has.

E.g.

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

What is a reliable way of ascertaining the value of appIsRunningInBlueStacks?

EDIT Summary of answers to comments on question:

Ben, Taras, thanks for the suggestions. The Build.MODEL etc. values for BlueStacks are:

  • Model: "GT-I9100"

  • Manufacturer: "samsung"

  • Device: "GT-I9100"

  • Product: "GT-I9100"

This is the same model number as the Samsung Galaxy SII so it would not be ideal to use this for fear of treating all users with SIIs the same as those on BlueStacks.

CommonsWare, the app continues to run in BlueStacks even with the < uses-feature> for multitouch in the manifest. In fact (also answering iagreen's question)...

packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);

... returns true! This is to be expected I suppose as the emulator is convinced it is a Samsung Galaxy SII!

Therefore we are still without a way of reliably detecting whether an app is running on BlueStacks without also throwing all Samsung Galaxy SII users in the same bucket. Any other ideas?

Overcompensation answered 3/1, 2013 at 17:20 Comment(7)
Have you tried peeking through android.os.Build? (developer.android.com/reference/android/os/Build.html)Botticelli
Yes, try checking android.os.Build MODEL, MANUFACTURER, DEVICE, PRODUCT constants at runtime and checking their values, than simply check one of the parameter that works best and is unique at runtime.Fanatic
Do you have the proper <uses-feature> elements to advertise that you require multitouch? Or is BlueStacks ignoring that?Vinna
@Taras: IIRC from a previous question, BlueStacks advertises itself as being a Galaxy Tab or some such, and so those Build values may not be as helpful as normal in this case.Vinna
Does BlueStacks correctly report FEATURE_TOUCHSCREEN_MULTITOUCH from the package manager? That seems the best way to go because then you gracefully degrade for all non-multitouch devices.Matrass
Run adb shell getprop and look for anything that stands out. Emulators often have some unique set of system properties.Subtype
github.com/framgia/android-emulator-detectorSphygmic
E
6

All the above methods are not working on BlueStacks 5. The correct way to do is checking if the path of /mnt/windows/BstSharedFolder exists. It is working fine on both BlueStacks 4 and 5.

   fun checkFilesExist(files: Array<String>): Boolean {
        files.forEach {
            val file = File(it)
            if (file.exists()) {
                return true
            }
        }
        return false
    }
    
    fun isBlueStacks(): Boolean {
        val BLUE_STACKS_FILES = arrayOf(
            "/mnt/windows/BstSharedFolder"
        )
        return checkFilesExist(BLUE_STACKS_FILES)
    }

Expectoration answered 7/1, 2022 at 1:44 Comment(1)
I've marked this as the accepted answer as it is the most recent. If you could add a working code snippet to your answer that would improve it even further. Thank you.Overcompensation
D
5

You can check that the Bluestacks shared folder exist /sdcard/windows/BstSharedFolder

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

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

        return false;
        }
Dominik answered 23/10, 2015 at 16:0 Comment(0)
R
3

After trying all the suggested solutions available online we found the Google's SafetyNet Attestation API is the only solution for detecting VMs like BlueStack(any version) and NoxPlayer.

Apps that care about content piracy (and other security issues) can filter their availability on the Google Play like Netflix filters devices on the PlayStore.

The new “device catalog” section of the console includes an option called “SafetyNet exclusion,” which can be used to prevent “devices that fail integrity tests or those that are uncertified by Google,” from downloading a specific app: among these would be rooted devices and those running custom ROMs.

But there is a catch user will still find the APK from cross-sharing or other distribution systems, so the client must implement SafetyNet Attestation API on the app level.

How does it work?

SafetyNet examines software and hardware information on the device where your app is installed to create a profile of that device. The service then attempts to find this same profile within a list of device models that have passed Android compatibility testing. The API also uses this software and hardware information to help you assess the basic integrity of the device, as well as the APK information of the calling app. This attestation helps you to determine whether or not the particular device has been tampered with or otherwise modified.

It's an (easy to implement) paid API from the Google which allows 10,000 free hits per day as of now :\

If anyone is interested in detecting VMs by them self, these are the good papers available suggesting heuristic approaches :

Evading Android Runtime Analysis via Sandbox Detection

Rage Against the Virtual Machine: Hindering Dynamic Analysis of Android Malware

Rendarender answered 24/8, 2018 at 11:3 Comment(0)
M
2

My version of BlueStacks is reporting my Build.Model as GT-N7100.

Using: android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER) I get Bluestacks.

Materially answered 23/1, 2015 at 20:0 Comment(0)
P
2

It maybe too late but for the sake of others who have the same problem :

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");
}
Peipus answered 23/3, 2018 at 8:23 Comment(0)
H
1

Based on Mr. Regis' answer, you can detect it when the shared folder is present. However in Bluestacks 4, using file.exists() will only return false. This is because the shared folder has no permissions (000 or ----------). But listing files in the directory will detect the folder.

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, it's a bluestacks emu");
    }
}
Hirai answered 29/1, 2019 at 13:19 Comment(1)
listFiles return nullPoirer
F
-1

This Will be unique.

There is no bluetooth device in Bluestack.

So try to get The Bluetooth Address string which is always 'null' on Bluestack or Any emulator.Make sure you are adding Bluetooth permission on your project manifest.

BluetoothAdapter m_BluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

 String m_bluetoothAdd = m_BluetoothAdapter.getAddress();
Freer answered 14/5, 2016 at 12:16 Comment(1)
Unlike other typical and non-working answers, this one really works (however, bluetooth permission is needed)Blakemore

© 2022 - 2024 — McMap. All rights reserved.