我希望我的代码在模拟器上运行时与在设备上运行时略有不同。(例如,使用10.0.2.2代替公共URL在开发服务器上自动运行。)检测Android应用程序何时在模拟器中运行的最佳方法是什么?
当前回答
试试这个方法。
在谷歌和Genymotion模拟器上测试。
public Boolean IsVM() {
String radioVersion = android.os.Build.getRadioVersion();
return radioVersion == null || radioVersion.isEmpty() || radioVersion.equals("1.0.0.0");
}
其他回答
无论您使用哪种代码来进行模拟器检测,我都强烈建议编写单元测试来覆盖所有构建。指纹,构建。硬件和构建。您所依赖的制造商值。下面是一些测试示例:
@Test
public void testIsEmulatorGenymotion() throws Exception {
assertThat(
DeviceUtils.isRunningOnEmulator(
"generic/vbox86p/vbox86p:4.1.1/JRO03S/eng.buildbot.20150217.102902:userdebug/test-keys",
"vbox86", "Genymotion")).isTrue();
assertThat(
DeviceUtils.isRunningOnEmulator(
"generic/vbox86p/vbox86p:5.1/LMY47D/buildbot06092001:userdebug/test-keys", "vbox86",
"Genymotion")).isTrue();
}
@Test
public void testIsEmulatorDefaultAndroidEmulator() throws Exception {
assertThat(
DeviceUtils.isRunningOnEmulator(
"generic_x86/sdk_google_phone_x86/generic_x86:5.0.2/LSY66H/1960483:eng/test-keys", "goldfish",
"unknown")).isTrue();
assertThat(
DeviceUtils.isRunningOnEmulator(
"Android/sdk_google_phone_x86_64/generic_x86_64:6.0/MASTER/2469028:userdebug/test-keys",
"ranchu", "unknown")).isTrue();
}
@Test
public void testIsEmulatorRealNexus5() throws Exception {
assertThat(
DeviceUtils.isRunningOnEmulator("google/hammerhead/hammerhead:6.0.1/MMB29K/2419427:user/release-keys",
"hammerhead", "LGE")).isFalse();
}
...下面是我们的代码(为了简洁起见,删除了调试日志和注释):
public static boolean isRunningOnEmulator() {
if (sIsRunningEmulator == null) {
sIsRunningEmulator = isRunningOnEmulator(Build.FINGERPRINT, Build.HARDWARE, Build.MANUFACTURER);
}
return sIsRunningEmulator;
}
static boolean isRunningOnEmulator(String fingerprint, String hardware, String manufacturer) {
boolean isEmulatorFingerprint = fingerprint.endsWith("test-keys");
boolean isEmulatorManufacturer = manufacturer.equals("Genymotion")
|| manufacturer.equals("unknown");
if (isEmulatorFingerprint && isEmulatorManufacturer) {
return true;
} else {
return false;
}
}
实际上,ANDROID_ID在2.2上总是等于9774D56D682E549C(根据这个线程+我自己的实验)。
所以,你可以这样检查:
String androidID = ...;
if(androidID == null || androidID.equals("9774D56D682E549C"))
do stuff;
虽然不是最漂亮的,但也很管用。
另一种选择是查看ro。硬件属性,看看它是否设置为金鱼。不幸的是,在Java中似乎没有一个简单的方法来做到这一点,但在C中使用property_get()是很简单的。
我收集了关于这个问题的所有答案,并提出了一个函数来检测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和Bluestacks上测试(2015年10月1日)
由于Genymotion的底层模拟引擎是VirtualBox,这不会很快改变,我发现以下代码是最可靠的:
public static boolean isGenymotion() {
return Build.PRODUCT != null && Build.PRODUCT.contains("vbox");
}
推荐文章
- Android M权限:对shouldShowRequestPermissionRationale()函数的使用感到困惑
- 为什么构建类型与产品风味不同?
- 我如何在一个片段中访问getSupportFragmentManager() ?
- 调试在哪里。Android Studio中的密钥存储库
- 从资产中读取文件
- 在不活动的地方调用getLayoutInflater()
- 设置Android布局元素的背景颜色
- 错误:'keytool'不能被识别为内部或外部命令、可操作程序或批处理文件
- 在应用程序本身中更改Locale
- apk (.apk)和应用程序包(.aab)的区别
- 如何设置超时在改造库?
- Android - SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
- TextView的字体大小在Android应用程序改变字体大小从本机设置
- 如何模拟Android杀死我的进程
- 禁用EditText闪烁光标