我怎么能当一个Android应用程序在模拟器中运行检测?我怎么能当一个Android应用程序在模拟器

2019-05-10 10:21发布

我想对仿真器的设备上运行时相比,运行时,运行我的代码略有不同。 ( 例如 ,使用10.0.2.2,而不是一个公共URL的反对开发服务器自动运行。)什么是当一个Android应用程序在模拟器中运行,以检测的最佳方式?

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


Answer 2:

一个常见的一个SEMS是Build.FINGERPRINT.contains("generic")



Answer 3:

那么Android的ID不适合我,我目前使用的工作:

"google_sdk".equals( Build.PRODUCT );


Answer 4:

根据来自其他答案的提示,这可能是最可靠的方法:

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



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

} 


Answer 6:

此代码对我的作品

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

在这情况下,设备没有SIM卡,它retuns空字符串:“”

由于Android模拟器总是retuns“Android”的网络运营商,我用上面的代码。



Answer 7:

两者都设置为“google_sdk”以下内容:

Build.PRODUCT
Build.MODEL

所以它应该是足够使用以下行的任何一个。

"google_sdk".equals(Build.MODEL)

要么

"google_sdk".equals(Build.PRODUCT)


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

仅供参考 - 我发现我的Kindle Fire有Build.BRAND =“通用”,以及一些仿真器没有为网络运营商的“Android”。



Answer 9:

我只是寻找_sdk_sdk_sdk_ ,甚至只是sdk部分Build.PRODUCT

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


Answer 10:

我从来没有发现一个好办法告诉你,如果在模拟器是。

但如果你只需要,如果你在开发环境中,你可以做到这一点是要detecet:

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

希望这有助于....



Answer 11:

不知道是否有更好的方法来检测动车组,但仿真器将具有文件init.goldfish.rc在根目录下。

这是仿真器特定的启动脚本,它不应该出现在非模拟器版本。



Answer 12:

这里是我的解决方案(如果你运行你的调试机器上的网络服务器,它仅适用):我已创建的应用程序启动时启动一个后台任务。 它看起来对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("");


Answer 13:

使用此功能:

 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;

    }


Answer 14:

您可以查看IMEI#, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29

如果我在模拟器上召回该返回0。然而,有没有文件,我可以找到它保证。 虽然仿真器可能不总是返回0,似乎很安全,一个登记的电话将在未安装SIM卡或一个当前未登记在返回0,会发生非电话Android设备上的东西,或者一个网络?

好像那会是一个坏主意,依靠它。

这也意味着你需要问权限读取手机状态,这是不好的,如果你不已经要求它别的东西。

如果不是,那么总有一些翻转位的地方,然后最终生成的签署应用程序。



Answer 15:

另一种办法是看ro.hardware属性,看看其设置为金鱼。 不幸的是,似乎没有要使用一个简单的方法来从Java做到这一点,但在C的琐碎property_get() 。



Answer 16:

上述建议的解决方案,以检查ANDROID_ID为我工作,直到我今天更新到了Android 2.2最新发布的SDK工具。

因此,我现在切换到跟随的解决方案,到目前为止有缺点但工作,你需要把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);
    }
} 


Answer 17:

从电池,模拟器:电源始终AC充电器。 温度始终为0。

你也可以使用Build.HOST记录主机值,不同的仿真器具有不同的主机值。



Answer 18:

在一个方法的所有答案

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


Answer 19:

我找到了新的模拟器Build.HARDWARE = "ranchu"

参考: https://groups.google.com/forum/#!topic/android-emulator-dev/dltBnUW_HzU

而且我发现,以检查是否仿真器或not.I认为这是对我们很好的借鉴Android的官方途径。

由于Android API级别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检查是否仿真器。

由于Android API级别24 [7.0的Android]

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。



Answer 20:

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

这应该如果应用程序是在模拟器上运行返回true。

我们应该小心,因为只有几个不同的仿真器没有检测到所有的模拟器。 这是很容易检查。 我们必须确保实际的设备不被检测为仿真器。

我用所谓的“应用程序的Android设备信息共享 ”进行检查。

在这个程序,你可以看到各种各样的许多设备的信息(在世界上可能是最设备;如果您正在使用的设备列表中缺少,它会自动添加)。



Answer 21:

其实,ANDROID_ID在2.2总是等于9774D56D682E549C(根据此线程 +我自己的实验)。

所以,你可以检查是这样的:

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

不是最漂亮的,但它的工作。



Answer 22:

这对我的作品

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


Answer 23:

将在仿真器的文件系统中的文件; 因为该文件将不会在实际设备上存在,这应该是稳定,可靠和易于当它打破修复。



Answer 24:

我收集了关于这个问题的所有答案,想出了功能,如果Android是在虚拟机/模拟器中运行,以检测:

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和蓝叠(2015年10月1日)。



Answer 25:

我的建议:

试试这个从GitHub。

容易察觉Android模拟器

  • 在设备农场经过在真实设备( https://aws.amazon.com/device-farm/ )
  • 蓝叠
  • Genymotion
  • Android模拟器
  • 安迪46.2.207.0
  • MEMU戏
  • 氮氧化物应用播放器
  • Koplayer
  • .....

如何用一个例子来使用:

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

                    }
                });


Answer 26:

检查答案,他们没有使用LeapDroid,Droid4x或安迪仿真器工作时,

什么工作,为所有的情况如下:

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


Answer 27:

谷歌使用的验证码设备信息插件颤振来决定,如果该设备是一个模拟器:

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


Answer 28:

if ("sdk".equals( Build.PRODUCT )) {
 // Then you are running the app on the emulator.
        Log.w("MyAPP", "\n\n  Emulator \n\n"); 
}


Answer 29:

if (Build.BRAND.equalsIgnoreCase("generic")) {
    // Is the emulator
}

所有生成引用build.prop值,所以你要考虑到,如果你要将此放入发布代码,你可能有一些用户已经修改他们无论出于何种原因根源。 有迹象表明,需要使用通用的品牌,除非特别试图仿效模拟器几乎没有修改。

指纹是构建编译和内核编译签名。 有建立使用通用的,通常直接从谷歌来源。

上已被修改的设备,该IMEI具有被归零,以及一种可能性,使得是不可靠的,除非你阻塞改性装置完全。

金鱼是基本的Android构建其他所有设备均从延长。 每一个Android设备具有init.goldfish.rc除非黑客入侵,原因不明去除。



Answer 30:

由于对Genymotion底层模拟引擎是VirtualBox和这不会很快改变任何时候我发现下面的代码最可靠的:

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


文章来源: How can I detect when an Android application is running in the emulator?