Detección del emulador de Android


Recientemente vi que cierto cliente tiene un método para detectar emuladores. Mi teléfono móvil normal fue juzgado como un emulador. Tenía curiosidad, así que busqué el motivo.

El código de detección común es el siguiente:

public boolean isEmulator() {
    
    
    String url = "tel:" + "123456";
    Intent intent = new Intent();
    intent.setData(Uri.parse(url));
    intent.setAction(Intent.ACTION_DIAL);
    // 是否可以处理跳转到拨号的 Intent
    boolean canResolveIntent = intent.resolveActivity(mContext.getPackageManager()) != null;

    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.SERIAL.equalsIgnoreCase("unknown")
        || Build.SERIAL.equalsIgnoreCase("android")
        || 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)
        || ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
            .getNetworkOperatorName().toLowerCase().equals("android")
        || !canResolverIntent;
}

Hay dos problemas con este simulador de instrumentación de código:

1. La detección de acceso telefónico, Android 10.0 y superior es falsa

2. Build.SERIAL, Android8.0 y superiores son todos desconocidos

Esto hace que los sistemas superiores a 8.0 sean mal juzgados.

Método de detección del simulador recomendado:

Código de detección de información del dispositivo:
private static final String[] known_numbers = {
    
    "15555215554", "15555215556", "15555215558", "15555215560", "15555215562", "15555215564", "15555215566", "15555215568", "15555215570", "15555215572", "15555215574", "15555215576", "15555215578", "15555215580", "15555215582", "15555215584",};

private boolean detectEmulator() {
    
    
        if (Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.startsWith("unknown")
                || 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)) {
    
    
            return true;
        }
        if (Build.PRODUCT.equals("sdk") || Build.PRODUCT.equals("sdk_x86")
                || Build.PRODUCT.equals("vbox86p") || Build.PRODUCT.equals("emulator")) {
    
    
            return true;
        }
        if (Build.BOARD == null) {
    
    
            return true;
        }
        if (Build.BOARD.equals("unknown")
                || Build.BOARD.contains("android")
                || Build.BOARD.contains("droid")) {
    
    
            return true;
        }
        if (Build.DEVICE == null) {
    
    
            return true;
        }
        if (Build.DEVICE.equals("unknown")
                || Build.DEVICE.contains("android")
                || Build.DEVICE.contains("droid")) {
    
    
            return true;
        }
        if (Build.HARDWARE == null) {
    
    
            return true;
        }
        if (Build.HARDWARE.equals("goldfish")
                || Build.HARDWARE.equals("ranchu")
                || Build.HARDWARE.contains("ranchu")) {
    
    
            return true;
        }
        if (Build.BRAND == null) {
    
    
            return true;
        }
        if (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) {
    
    
            return true;
        }
        if (Build.MANUFACTURER.equals("unknown")) {
    
    
            return true;
        }
        if (Build.MANUFACTURER.equals("Genymotion")) {
    
    
            return true;
        }
        if ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
                || "google_sdk".equals(Build.PRODUCT)) {
    
    
            return true;
        }
        if (Build.PRODUCT == null) {
    
    
            return true;
        }
        if (Build.PRODUCT.equals("sdk")
                || Build.PRODUCT.equals("sdk_x86")
                || Build.PRODUCT.equals("vbox86p")
                || Build.PRODUCT.equals("emulator")) {
    
    
            return true;
        }
        if (Build.HARDWARE.equals("goldfish")
                || Build.HARDWARE.equals("ranchu")) {
    
    
            return true;
        }
        if (Build.FINGERPRINT.startsWith("generic")
                || Build.FINGERPRINT.startsWith("unknown")
                || 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)) {
    
    
            return true;
        }
        if (Build.PRODUCT == null) {
    
    
            return true;
        }
        if (Build.PRODUCT.equals("sdk")
                || Build.PRODUCT.equals("sdk_x86")
                || Build.PRODUCT.equals("vbox86p")
                || Build.PRODUCT.equals("emulator")) {
    
    
            return true;
        }
        if (Build.HARDWARE.equals("goldfish")
                || Build.HARDWARE.equals("ranchu")) {
    
    
            return true;
        }
        if (new File("/dev/socket/qemud").exists()
                || new File("/dev/qemu_pipe").exists()) {
    
    
            return true;
        }
        try {
    
    
            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            if (telephonyManager != null) {
    
    
                String deviceId = telephonyManager.getDeviceId();
                List<String> knownNumbers = Arrays.asList(known_numbers);
                if (knownNumbers.contains(deviceId)) {
    
    
                    return true;
                }
            }
        } catch (Exception e) {
    
    
        }
        return false;
    }

El código anterior utiliza una variedad de métodos para detectar si el dispositivo es un emulador, que incluyen:

  • Compruebe si Build.FINGERPRINT comienza con "genérico" o "desconocido"
  • Compruebe si Build.MODEL contiene "google_sdk", "Emulator" o "Android SDK creado para x86"
  • Compruebe si Build.MANUFACTURER es "Genymotion"
  • Compruebe si Build.PRODUCT es "sdk", "sdk_x86", "vbox86p" o "emulator"
  • Compruebe si Build.BOARD es "desconocido" o contiene "android" o "droid"
  • Compruebe si Build.DEVICE es "desconocido" o contiene "android" o "droid"
  • Compruebe si Build.HARDWARE es "goldfish", "ranchu" o contiene "ranchu"
  • Compruebe si Build.BRAND comienza con "generic" y Build.DEVICE comienza con "generic"
  • Compruebe si Build.PRODUCT es "google_sdk"
  • Detectar si existe el archivo "/dev/socket/qemud" o "/dev/qemu_pipe"
  • Detectar si el número de teléfono del dispositivo es un número de teléfono conocido del emulador

Todos los métodos anteriores se basan en la información del firmware. A través de las pruebas, se descubre que muchos simuladores no son válidos. Consulte los tutoriales en línea, así como la detección de Bluetooth, sensor de luz y CPU. Con la información del firmware anterior, básicamente puede manejar la mayoría simuladores.

Código de detección de Bluetooth:
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;
        }
    }
}
Código de detección del sensor de luz:
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;
    }
}
Código de detección de CPU:
public static boolean checkIsNotRealPhone() {
    
    
    String cpuInfo = readCpuInfo();
    if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
    
    
        return true;
    }
    return false;
}

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;
}

El método de detección anterior no es del todo factible. Con la actualización del sistema Android y el aumento de emuladores, necesitamos estudiar específicamente algunos cambios correspondientes para actualizar el código anterior.

Debemos prestar atención a un problema durante las pruebas: es posible que no podamos detectar todos los emuladores, pero no debemos matar accidentalmente las máquinas reales.
Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/u010671061/article/details/135241186
Recomendado
Clasificación