我希望我的代码在模拟器上运行时与在设备上运行时略有不同。(例如,使用10.0.2.2代替公共URL在开发服务器上自动运行。)检测Android应用程序何时在模拟器中运行的最佳方法是什么?
当前回答
我只是寻找_sdk, _sdk_或sdk_,甚至只是sdk部分构建。产品:
if(Build.PRODUCT.matches(".*_?sdk_?.*")){
//-- emulator --
}else{
//-- other device --
}
其他回答
这对我很有用
public boolean isEmulator() {
return Build.MANUFACTURER.equals("unknown");
}
实际上,ANDROID_ID在2.2上总是等于9774D56D682E549C(根据这个线程+我自己的实验)。
所以,你可以这样检查:
String androidID = ...;
if(androidID == null || androidID.equals("9774D56D682E549C"))
do stuff;
虽然不是最漂亮的,但也很管用。
无论您使用哪种代码来进行模拟器检测,我都强烈建议编写单元测试来覆盖所有构建。指纹,构建。硬件和构建。您所依赖的制造商值。下面是一些测试示例:
@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;
}
}
Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
如果应用程序在模拟器上运行,这应该返回true。
我们应该注意的是不要检测所有的模拟器,因为只有几个不同的模拟器。这很容易检查。 我们必须确保实际的设备不会被检测为模拟器。
我使用名为“Android设备信息共享”的应用程序来检查这一点。
在这个应用程序上,你可以看到许多设备的各种信息(可能是世界上大多数设备;如果您正在使用的设备不在列表中,它将自动添加)。
检查设备是否安装了这些包是一个好主意:
mListPackageName.add("com.google.android.launcher.layouts.genymotion");
mListPackageName.add("com.bluestacks");
mListPackageName.add("com.vphone.launcher");
mListPackageName.add("com.bignox.app");
我只是把它放在一个数组列表中…
然后简单地检查包管理器,直到找到一个。
private static boolean isEmulByPackage(Context context) {
final PackageManager pm = context.getPackageManager();
for (final String pkgName : mListPackageName) {
return isPackageInstalled(pkgName, pm);
}
return false;
}
private static boolean isPackageInstalled(final String packageName, final PackageManager packageManager) {
try {
packageManager.getPackageInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
请注意,VM很可能有一些方法来欺骗应用程序,在这种情况下,可能有必要查看一些虚拟设备中不存在的物理传感器。
推荐文章
- 我如何在一个片段中访问getSupportFragmentManager() ?
- 调试在哪里。Android Studio中的密钥存储库
- 从资产中读取文件
- 在不活动的地方调用getLayoutInflater()
- 设置Android布局元素的背景颜色
- 错误:'keytool'不能被识别为内部或外部命令、可操作程序或批处理文件
- 在应用程序本身中更改Locale
- apk (.apk)和应用程序包(.aab)的区别
- 如何设置超时在改造库?
- Android - SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
- TextView的字体大小在Android应用程序改变字体大小从本机设置
- 如何模拟Android杀死我的进程
- 禁用EditText闪烁光标
- Android Eclipse -无法找到*.apk
- 设置TextView文本从html格式的字符串资源在XML