我希望我的代码在模拟器上运行时与在设备上运行时略有不同。(例如,使用10.0.2.2代替公共URL在开发服务器上自动运行。)检测Android应用程序何时在模拟器中运行的最佳方法是什么?
当前回答
由于Genymotion的底层模拟引擎是VirtualBox,这不会很快改变,我发现以下代码是最可靠的:
public static boolean isGenymotion() {
return Build.PRODUCT != null && Build.PRODUCT.contains("vbox");
}
其他回答
您可以检查IMEI #, http://developer.android.com/reference/android/telephony/TelephonyManager.html#getDeviceId%28%29
如果我在模拟器上调用这个返回0。然而,我找不到任何文件可以保证这一点。虽然模拟器可能不总是返回0,但注册的电话不返回0似乎是相当安全的。在非手机的安卓设备上,或者没有安装SIM卡,或者没有在网络上注册的设备上,会发生什么呢?
似乎这是个坏主意,依赖于它。
这也意味着你需要获得读取手机状态的许可,如果你不需要它来做其他事情,这是很糟糕的。
如果不是这样,那么在你最终生成签名应用之前,总是会有一些翻转。
if (Build.BRAND.equalsIgnoreCase("generic")) {
// Is the emulator
}
所有BUILD引用都是BUILD。道具值,所以你必须考虑到如果你要把这个放到发布代码中,你可能会有一些根用户因为某种原因修改了他们的。实际上没有任何修改需要使用generic作为品牌,除非特别尝试模拟模拟器。
指纹是构建编译和内核编译签名。有一些构建使用通用的,通常直接来自谷歌。
在修改过的设备上,IMEI也有可能被归零,所以这是不可靠的,除非您完全阻止修改过的设备。
金鱼是所有其他设备扩展的基础android构建。每个Android设备都有一个init.金鱼.rc,除非被黑客攻击并出于未知原因删除。
另一个选择是检查你是在调试模式还是生产模式:
if (BuildConfig.DEBUG){日志。i(TAG,“我在调试模式”);}
简单可靠。
这并不是问题的全部答案,但在大多数情况下,您可能想要区分用户群的调试/测试会话和生命会话。
在我的情况下,我在调试模式下将谷歌分析设置为dryRun(),因此这种方法完全适合我。
对于更高级的用户,还有另一种选择。Gradle构建变量:
在你的应用程序的gradle文件中添加一个新的变体:
buildTypes {
release {
// some already existing commands
}
debug {
// some already existing commands
}
// the following is new
test {
}
}
在你的代码中检查构建类型:
if ("test".equals(BuildConfig.BUILD_TYPE)) { Log.i(TAG, "I am in Test build type"); }
else if ("debug".equals(BuildConfig.BUILD_TYPE)) { Log.i(TAG, "I am in Debug build type"); }
现在你有机会构建3种不同类型的应用程序。
试试这个方法。
在谷歌和Genymotion模拟器上测试。
public Boolean IsVM() {
String radioVersion = android.os.Build.getRadioVersion();
return radioVersion == null || radioVersion.isEmpty() || radioVersion.equals("1.0.0.0");
}
使用这个函数:
public static final boolean isEmulator() {
int rating = 0;
if ((Build.PRODUCT.equals("sdk")) || (Build.PRODUCT.equals("google_sdk"))
|| (Build.PRODUCT.equals("sdk_x86")) || (Build.PRODUCT.equals("vbox86p"))) {
rating++;
}
if ((Build.MANUFACTURER.equals("unknown")) || (Build.MANUFACTURER.equals("Genymotion"))) {
rating++;
}
if ((Build.BRAND.equals("generic")) || (Build.BRAND.equals("generic_x86"))) {
rating++;
}
if ((Build.DEVICE.equals("generic")) || (Build.DEVICE.equals("generic_x86")) || (Build.DEVICE.equals("vbox86p"))) {
rating++;
}
if ((Build.MODEL.equals("sdk")) || (Build.MODEL.equals("google_sdk"))
|| (Build.MODEL.equals("Android SDK built for x86"))) {
rating++;
}
if ((Build.HARDWARE.equals("goldfish")) || (Build.HARDWARE.equals("vbox86"))) {
rating++;
}
if ((Build.FINGERPRINT.contains("generic/sdk/generic"))
|| (Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86"))
|| (Build.FINGERPRINT.contains("generic/google_sdk/generic"))
|| (Build.FINGERPRINT.contains("generic/vbox86p/vbox86p"))) {
rating++;
}
return rating > 4;
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件