我希望我的代码在模拟器上运行时与在设备上运行时略有不同。(例如,使用10.0.2.2代替公共URL在开发服务器上自动运行。)检测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很可能有一些方法来欺骗应用程序,在这种情况下,可能有必要查看一些虚拟设备中不存在的物理传感器。
其他回答
试试这个方法。
在谷歌和Genymotion模拟器上测试。
public Boolean IsVM() {
String radioVersion = android.os.Build.getRadioVersion();
return radioVersion == null || radioVersion.isEmpty() || radioVersion.equals("1.0.0.0");
}
用下面的代码来判断你的应用是否使用了调试键?它没有检测模拟器,但它可能为您的目的工作?
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;
}
我尝试了几种技术,但最终选择了稍微修改过的检查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"。
无论您使用哪种代码来进行模拟器检测,我都强烈建议编写单元测试来覆盖所有构建。指纹,构建。硬件和构建。您所依赖的制造商值。下面是一些测试示例:
@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 Studio下[运行>编辑配置…]发射旗
在启动标志中添加以下内容…
--ei running_emulator 1
然后在你的onCreate活动中
Bundle extras = getIntent().getExtras();
if (extras.getInt("running_emulator", 0) == 1) {
//Running in the emulator!... Make USE DEV ENV!!
}
简单!
推荐文章
- Android M权限:对shouldShowRequestPermissionRationale()函数的使用感到困惑
- 为什么构建类型与产品风味不同?
- 我如何在一个片段中访问getSupportFragmentManager() ?
- 调试在哪里。Android Studio中的密钥存储库
- 从资产中读取文件
- 在不活动的地方调用getLayoutInflater()
- 设置Android布局元素的背景颜色
- 错误:'keytool'不能被识别为内部或外部命令、可操作程序或批处理文件
- 在应用程序本身中更改Locale
- apk (.apk)和应用程序包(.aab)的区别
- 如何设置超时在改造库?
- Android - SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
- TextView的字体大小在Android应用程序改变字体大小从本机设置
- 如何模拟Android杀死我的进程
- 禁用EditText闪烁光标