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


当前回答

这个代码适用于我

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

如果该设备没有sim卡,它将返回空字符串:""

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

其他回答

我从来没有找到一个很好的方法来判断你是否在模拟器中。

但如果你只是需要检测你是否在开发环境中,你可以这样做:

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

希望对大家有所帮助....

这个解决方案怎么样(SystemProperties的类实现在这里可用):

val isProbablyRunningOnEmulator: Boolean by lazy {
    // Android SDK emulator
    return@lazy ((Build.MANUFACTURER == "Google" && Build.BRAND == "google" &&
            ((Build.FINGERPRINT.startsWith("google/sdk_gphone_")
                    && Build.FINGERPRINT.endsWith(":user/release-keys")
                    && Build.PRODUCT.startsWith("sdk_gphone_")
                    && Build.MODEL.startsWith("sdk_gphone_"))
                    //alternative
                    || (Build.FINGERPRINT.startsWith("google/sdk_gphone64_")
                    && (Build.FINGERPRINT.endsWith(":userdebug/dev-keys") || Build.FINGERPRINT.endsWith(":user/release-keys"))
                    && Build.PRODUCT.startsWith("sdk_gphone64_")
                    && Build.MODEL.startsWith("sdk_gphone64_"))))
            //
            || 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")
            //bluestacks
            || "QC_Reference_Phone" == Build.BOARD && !"Xiaomi".equals(Build.MANUFACTURER, ignoreCase = true)
            //bluestacks
            || Build.MANUFACTURER.contains("Genymotion")
            || Build.HOST.startsWith("Build")
            //MSI App Player
            || Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
            || Build.PRODUCT == "google_sdk"
            // another Android SDK emulator check
            || SystemProperties.getProp("ro.kernel.qemu") == "1")
}

请注意,一些模拟器伪造真实设备的精确规格,因此可能无法检测到它。我已经添加了我能添加的东西,但我不认为有100%的方法来检测它是否真的是一个模拟器。

这里有一个你可以在APK中创建的小片段来展示关于它的各种事情,所以你可以添加自己的规则:

        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"

我找到了新的模拟器Build。硬件= "ranchu"。

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

而且我还找到了Android官方的方法来检查是否是模拟器。我认为这对我们是很好的参考。

Android API Level 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来检查emulator是否。

Android API Level 24 [Android 7.0]

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来检查emulator是否。

官方检查模拟器的方式是不是新的,也可能不够,上面的答案也提到了。

但这可能告诉我们,官方将提供官方检查是否模拟器的方法。

正如使用上面提到的所有方法一样,现在我们也可以使用这两种方法来检查模拟器是否正确。

如何访问com.android.internal包和@hide

并等待官方的开放SDK。

由于Genymotion的底层模拟引擎是VirtualBox,这不会很快改变,我发现以下代码是最可靠的:

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

试试这个方法。

在谷歌和Genymotion模拟器上测试。

public Boolean IsVM() {
    String radioVersion = android.os.Build.getRadioVersion();
    return radioVersion == null || radioVersion.isEmpty() || radioVersion.equals("1.0.0.0");
}