How can I detect when an Android application is running in the emulator?

前端 未结 30 2323
无人及你
无人及你 2020-11-22 16:42

I would like to have my code run slightly differently when running on the emulator than when running on a device. (For example, using 10.0.2.2 instead of a

相关标签:
30条回答
  • 2020-11-22 17:26

    How about this solution (class implementation of SystemProperties is available here):

    fun isProbablyAnEmulator(): Boolean {
        return (Build.FINGERPRINT.startsWith("google/sdk_gphone_")
                && Build.FINGERPRINT.endsWith(":user/release-keys")
                && Build.MANUFACTURER == "Google" && Build.PRODUCT.startsWith("sdk_gphone_") && Build.BRAND == "google"
                && Build.MODEL.startsWith("sdk_gphone_")) // Android SDK emulator
                || 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")
                || "QC_Reference_Phone" == Build.BOARD  //bluestacks
                || Build.MANUFACTURER.contains("Genymotion")
                || Build.HOST.startsWith("Build") //MSI App Player
                || Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
                || Build.PRODUCT == "google_sdk"
                || SystemProperties.getProp("ro.kernel.qemu") == "1"// another Android SDK emulator check
    }
    

    Note that some emulators fake exact specs of real devices, so it might be impossible to detect it.

    Here a tiny snippet you can make in the APK to show various things about it, so you could add your own rules:

            textView.text = "FINGERPRINT:${Build.FINGERPRINT}\n" +
                    "MODEL:${Build.MODEL}\n" +
                    "MANUFACTURER:${Build.MANUFACTURER}\n" +
                    "BRAND:${Build.BRAND}\n" +
                    "DEVICE:${Build.DEVICE}\n" +
                    "BOARD:${Build.BOARD}\n" +
                    "HOST:${Build.HOST}\n" +
                    "PRODUCT:${Build.PRODUCT}\n"
    
    0 讨论(0)
  • 2020-11-22 17:27

    you can check the IMEI #, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29

    if i recall on the emulator this return 0. however, there's no documentation i can find that guarantees that. although the emulator might not always return 0, it seems pretty safe that a registered phone would not return 0. what would happen on a non-phone android device, or one without a SIM card installed or one that isn't currently registered on the network?

    seems like that'd be a bad idea, to depend on that.

    it also means you'd need to ask for permission to read the phone state, which is bad if you don't already require it for something else.

    if not that, then there's always flipping some bit somewhere before you finally generate your signed app.

    0 讨论(0)
  • 2020-11-22 17:28

    One common one sems to be Build.FINGERPRINT.contains("generic")

    0 讨论(0)
  • 2020-11-22 17:30

    This works for me

    public boolean isEmulator() {
        return Build.MANUFACTURER.equals("unknown");
    }
    
    0 讨论(0)
  • 2020-11-22 17:32

    How about something like the code below to tell if your app was signed with the debug key? it's not detecting the emulator but it might work for your purpose?

    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;
    
    } 
    
    0 讨论(0)
  • 2020-11-22 17:32

    My recommendation:

    try this from github.

    Easy to detect android emulator

    • Checked on real devices in Device Farm (https://aws.amazon.com/device-farm/)
    • BlueStacks
    • Genymotion
    • Android Emulator
    • Andy 46.2.207.0
    • MEmu play
    • Nox App Player
    • Koplayer
    • .....

    How to use with an Example:

    EmulatorDetector.with(this)
                    .setCheckTelephony(true)
                    .addPackageName("com.bluestacks")
                    .setDebug(true)
                    .detect(new EmulatorDetector.OnEmulatorDetectorListener() {
                        @Override
                        public void onResult(boolean isEmulator) {
                            if(isEmulator){
                             // Do your work
                            }
                            else{
                            // Not emulator and do your work
                            }
                        }
                    });
    
    0 讨论(0)
提交回复
热议问题