Android判断模拟器还是真机

Home / Android MrLee 2018-11-10 3406

先吐槽一下,百度上搜出来的都是什么垃圾答案。各种抄袭来的代码,连原理都没讲清楚,或者代码功能都没有实现的,都一篇篇的文章发表在哪里。浪费了我不知道多少时间,真的,我快恶心的不行了。可以吗?能不能有点职业操守,抄代码自己用也就算了,你还当自己的文章发表了,你发表能用也就算了。功能还都是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 {
            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. 海马模拟器

通过这几款模拟器的检测,应该能说明这个方案比较可靠。

本文链接:https://www.it72.com/12416.htm

推荐阅读
最新回复 (0)
返回