我希望我的代码在模拟器上运行时与在设备上运行时略有不同。(例如,使用10.0.2.2代替公共URL在开发服务器上自动运行。)检测Android应用程序何时在模拟器中运行的最佳方法是什么?


当前回答

所有答案都在一个方法中

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

其他回答

我尝试了几种技术,但最终选择了稍微修改过的检查Build的版本。产品如下。这似乎变化很大,从模拟器到模拟器,这就是为什么我有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 = "generic",一些模拟器没有网络运营商的"Android"。

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

如果我在模拟器上调用这个返回0。然而,我找不到任何文件可以保证这一点。虽然模拟器可能不总是返回0,但注册的电话不返回0似乎是相当安全的。在非手机的安卓设备上,或者没有安装SIM卡,或者没有在网络上注册的设备上,会发生什么呢?

似乎这是个坏主意,依赖于它。

这也意味着你需要获得读取手机状态的许可,如果你不需要它来做其他事情,这是很糟糕的。

如果不是这样,那么在你最终生成签名应用之前,总是会有一些翻转。

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

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

我们应该注意的是不要检测所有的模拟器,因为只有几个不同的模拟器。这很容易检查。 我们必须确保实际的设备不会被检测为模拟器。

我使用名为“Android设备信息共享”的应用程序来检查这一点。

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

您可以检查deviceId (IMEI)是否为“000000000000000”(15个零)

我的建议:

试试github上的这个。

易于检测android模拟器

在设备场(https://aws.amazon.com/device-farm/)的真实设备上检查 BlueStacks Genymotion Android模拟器 安迪46.2.207.0 菜单玩 诺克斯应用播放器 Koplayer …

如何与示例一起使用:

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