Android判断模拟器还是真机的方法

作为一个App,我们在做推广的同时,肯定会担心刷量的问题。一般常见的刷量手段就是通过安卓模拟器进行刷量。
那就会想到,怎么判断一个设备是模拟器还是真机。
先吐槽一下,百度上搜出来的都是什么垃圾答案。各种抄袭来的代码,连原理都没讲清楚,或者代码功能都没有实现的,都一篇篇的文章发表在哪里。浪费了我不知道多少时间,真的,我快恶心的不行了。可以吗?能不能有点职业操守,抄代码自己用也就算了,你还当自己的文章发表了,你发表能用也就算了。功能还都是BUG。有没有素质啊。时间很贵的。
下面我把我研究的成果,当然有部分是参考别人的代码提供给大家。
先说思路。
1.那些说用IMei的,Mac值,Device_Id,以及Telephony_Service中的运营商,国家的,什么乱七八糟不靠谱的。首先都是错误的思路。
你们还以为现在的模拟器是Studio上的模拟器吗?求你们写代码之前,先研究一下模拟器的功能。夜神,逍遥,这些模拟器上面明明白白的写着,修改IMEI码,修改设备信息,修改运营商,手机号码等等等等。你和我说通过判断这些信息的默认值。
2.那些不靠谱的去除了,我们该如何去判断呢?
那就要判断一下是不是有什么硬件设备是模拟器上没有的呢?很容易想到的就是蓝牙功能。我们通过获取系统服务获取到蓝牙,判断蓝牙是否存在,然后发现模拟器也有蓝牙。不要慌,获取一下蓝牙的名称发现null。好了。再看看真机的效果。这就出来了。
/**
* 判断蓝牙是否有效来判断是否为模拟器
*
* @return true 为模拟器
*/
public boolean notHasBlueTooth() {
BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
if (ba == null) {
return true;
} else {
// 如果有蓝牙不一定是有效的。获取蓝牙名称,若为null 则默认为模拟器
String name = ba.getName();
if (TextUtils.isEmpty(name)) {
return true;
} else {
【Android判断模拟器还是真机的方法】return false;
}
}
}
我在做的时候就考虑,一个蓝牙是否足够!废话,当然不够啦。那还有什么呢?瞬间想到了传感器。温度,重力,光,还有其他一堆。经过测试发现,模拟器上也有很多传感器,同时有部分传感器没有。而在真机上,同样也有部分手机没有温度,压力等传感器。经过一个个的测试选择。我选择了光传感器。
/**
* 判断是否存在光传感器来判断是否为模拟器
* 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
* @return true 为模拟器
*/
public static Boolean notHasLightSensorManager(Context context) {
SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
Sensor sensor8 = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光
if (null == sensor8) {
return true;
} else {
return false;
}
}
既然模拟器都能模拟手机,那是不是模拟器出来的所有设备信息是不是有什么特征呢?通过打印一堆的Device参数。经过网上的参考。就是下面这个代码了。
/**
* 根据部分特征参数设备信息来判断是否为模拟器
*
* @return true 为模拟器
*/
public static boolean isFeatures() {
return Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.toLowerCase().contains("vbox")
|| Build.FINGERPRINT.toLowerCase().contains("test-keys")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT);
}
好了,和设备硬件相关的就差不多这几个方法了。那其他方法呢?那模拟器基本上都是运行在电脑上的,电脑的架构是X86。手机正常的是arm的。那是不是可以通过获取CPU来判断呢?基本上就是intel和amd两种吧?
public static String readCpuInfo() {
String result = "";
try {
String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
ProcessBuilder cmd = new ProcessBuilder(args);
Process process = cmd.start();
StringBuffer sb = new StringBuffer();
String readLine = "";
BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
while ((readLine = responseReader.readLine()) != null) {
sb.append(readLine);
}
responseReader.close();
result = sb.toString().toLowerCase();
} catch (IOException ex) {
}
return result;
}
/**
* 判断cpu是否为电脑来判断 模拟器
*
* @return true 为模拟器
*/
public static boolean checkIsNotRealPhone() {
String cpuInfo = readCpuInfo();
if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
return true;
}
return false;
}
好了,通过以上方法,你可以过滤一大堆的模拟器了。
当然我这些方法只是比较基础了。我在百度谷歌的时候当然也有部分大神的思路。
下面推荐一个通过 (匹配Qemu的一些特征文件以及属性) 来判断。这个我也不会。也没看懂。如果有需要的自己去查看吧。
https://github.com/happylishang/CacheEmulatorChecker
!!!!!!重要说明!!!!!!!!
经过N台设备测试以及N款模拟器测试。
1.逍遥模拟器竟然可以无视蓝牙检测。所以蓝牙的方法已经失效。
2.还是这个逍遥模拟器,又TMD设备特征参数也已经失效了。
3.所以经过多方测试发现,通过硬件信息去判断模拟器的方法已经失效了。现在唯一比较靠谱的应该就剩这个CPU的检测以及这个光传感器了吧?
4.如果有某位同学测试发现有模拟器可以过CPU检测以及光传感器的麻烦说一下。
5.测试的时候又发现了一个情况。如果你的项目里面加载了so。那就别用CPU检测了,那当然就是ARM的架构了。到了这里,那就只有光传感器了。
如果觉得不放心。那就请同学认真学习下面这篇文章中的关键点。
https://github.com/happylishang/CacheEmulatorChecker
我们最后的方案也是通过学习这个文章的思想,然后再自己拓展。
在Windows和Mac上测试不同的模拟器,检测出模拟器的有1.逍遥模拟器 2. 蓝叠模拟器 3. 夜神模拟器 4. 靠谱助手 5. 天天模拟器 6. 海马模拟器
通过这几款模拟器的检测,应该能说明这个方案比较可靠。
---------------------
作者:秋名山小尼玛
来源:CSDN
原文:https://blog.csdn.net/tianshuai4317618/article/details/78834683/
版权声明:本文为博主原创文章,转载请附上博文链接!

    推荐阅读