How to find out from code if my Android app runs o

2019-01-18 10:41发布

问题:

I have read this stackoverflow thread already and I tried using the code given in that answer to find out if I run my code on the emulator or on a real device:

import android.content.ContentResolver;
import android.provider.Settings.Secure;
...     
mTextView.setText(Secure.getString(getContentResolver(), Secure.ANDROID_ID));

On my real device it returns "2bccce3...", however on the emulator it does not return null, but also a string "bd9f8..."

Ideas how to find out if emulator or real device from code would be highly appreciated

回答1:

There's a rather old thread on Android Developers group that suggests checking the number of sensors on the device. Something like this might work:

SensorManager manager = (SensorManager) getSystemService(SENSOR_SERVICE);
if (manager.getSensorList(Sensor.TYPE_ALL).isEmpty()) {
    // running on an emulator
} else {
    // running on a device
}

I haven't tried this, so I have no idea how reliable the suggestion is. (Perhaps some emulators now report some sensors; perhaps some devices report no sensors. [Is there an Android toothbrush yet?]) But it can't be worse than checking for a null ANDROID_ID (which doesn't work as of 2.2).

P.S. Another thread claims that as of 2.2, the ANDROID_ID for the emulator is always "9774D56D682E549C". However, you are apparently getting some other hex string, so I don't think this is right, either.

P.P.S. Other suggestions I haven't tried are here. One that seems particularly nice (if it works) is:

if (android.os.Build.MODEL.equals(“google_sdk”)) {
   // emulator
} else {
   //not emulator
}


回答2:

This should do it:

boolean inEmulator = false;
String brand = Build.BRAND;
if (brand.compareTo("generic") == 0)
{
    inEmulator = true;
}

EDIT:

boolean inEmulator = "generic".equals(Build.BRAND.toLowerCase());


回答3:

With the advent of the new Intel native emulator the above mentioned methods did not work any longer. Now I am using this code snippet which works on both Intel and ARM emulators:

if (Build.MODEL.contains("google_sdk") ||
    Build.MODEL.contains("Emulator") ||
    Build.MODEL.contains("Android SDK")) {
  RunsInEmulator = true;
}


回答4:

I think that the best answer is to decide why you actually care to know - and then check for whatever specific characteristic of the emulator you believe requires that your app behave differently than it would on a device.



回答5:

How about this solution:

  public static boolean isRunningOnEmulator()
    {
    boolean result=//
        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");
    if(result)
      return true;
    result|=Build.BRAND.startsWith("generic")&&Build.DEVICE.startsWith("generic");
    if(result)
      return true;
    result|="google_sdk".equals(Build.PRODUCT);
    return result;
    }


回答6:

As stated in this post, IMEI and IMSI are harcoded on the emulator:

2325     { "+CIMI", OPERATOR_HOME_MCCMNC "000000000", NULL },   /* request internation subscriber identification number */
2326     { "+CGSN", "000000000000000", NULL },   /* request model version */



You can easily get the value using

adb shell dumpsys iphonesubinfo

So checking the device's IMEI using TelephonyManager.getDeviceId() should be sufficient to find out, whether you're on an emulator or a real device.


To be absolutely sure, you might combine it with checking the model name as stated by various other posts.

public static boolean isRunningOnEmulator(final Context inContext) {

    final TelephonyManager theTelephonyManager = (TelephonyManager)inContext.getSystemService(Context.TELEPHONY_SERVICE);
    final boolean hasEmulatorImei = theTelephonyManager.getDeviceId().equals("000000000000000");
    final boolean hasEmulatorModelName = Build.MODEL.contains("google_sdk")
            || Build.MODEL.contains("Emulator")
            || Build.MODEL.contains("Android SDK");

    return hasEmulatorImei || hasEmulatorModelName;
}


The downside to this approach is that you need a context to access this information and instantiating a TelephonyManager for every check.



回答7:

Following one is correctly detect my emulator

if (Build.BRAND.equalsIgnoreCase("generic")) {
              //"YES, I am an emulator"
       } else {
              //"NO, I am NOT an emulator"
       }