自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android模擬器檢測(cè)方法有哪些?

移動(dòng)開(kāi)發(fā) Android
隨著Android系統(tǒng)的更新,模擬器的增多,需要具體研究對(duì)應(yīng)的一些變動(dòng)來(lái)更新上述代碼。最終判定結(jié)果不一定能檢測(cè)出所有的模擬器,但是一定不能誤殺真機(jī)影響用戶(hù)正常使用。

Android模擬器的檢測(cè),一般方法是通過(guò)檢查設(shè)備的一些特征來(lái)判斷應(yīng)用是否運(yùn)行在模擬器。

  1. 檢查Build信息:通過(guò)讀取設(shè)備的Build信息來(lái)判斷是否在模擬器上運(yùn)行。例如,檢查設(shè)備的Build.MODEL和Build.MANUFACTURER是否包含常見(jiàn)的模擬器關(guān)鍵詞,如"generic"、"sdk"等。
  2. 檢查硬件特征:模擬器通常會(huì)模擬一些硬件特征,如IMEI、MAC地址等。通過(guò)檢查這些硬件特征來(lái)判斷是否在模擬器上運(yùn)行。
  3. 檢查虛擬化指令集:模擬器通常會(huì)使用虛擬化指令集來(lái)模擬硬件,通過(guò)檢查CPU的指令集來(lái)判斷是否在模擬器上運(yùn)行。
  4. 檢查運(yùn)行環(huán)境:通過(guò)檢查設(shè)備的運(yùn)行環(huán)境,如是否有電話(huà)功能、GPS功能等來(lái)判斷是否在模擬器上運(yùn)行。

這些方法都不是絕對(duì)可靠的,模擬器的不斷發(fā)展可能會(huì)繞過(guò)這些檢測(cè)方法。在實(shí)際應(yīng)用中,通過(guò)綜合多種方法進(jìn)行檢測(cè),以提高準(zhǔn)確性。

普遍檢測(cè)方法

public boolean isEmulator() {

    String url = "tel:" + "123456";
    Intent intent = new Intent();
    intent.setData(Uri.parse(url));
    intent.setAction(Intent.ACTION_DIAL);
    // 是否可以處理跳轉(zhuǎn)到撥號(hào)的 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;
}

以上方法檢測(cè)模擬器有兩個(gè)問(wèn)題:

  1. 撥號(hào)檢測(cè),Android10.0及以上均為false,Android10.0以上會(huì)誤判。
  2. Build.SERIAL,Android8.0以上均為unknown導(dǎo)致8.0以上系統(tǒng)均會(huì)被誤判。

推薦檢測(cè)方法

設(shè)備信息檢測(cè)
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;
}

上面方法使用了多種方法來(lái)檢測(cè)設(shè)備是否為模擬器,包括:

  • 檢測(cè) Build.FINGERPRINT 是否以 “generic” 或 “unknown” 開(kāi)頭
  • 檢測(cè) Build.MODEL 是否包含 “google_sdk”、“Emulator” 或 “Android SDK built for x86”
  • 檢測(cè) Build.MANUFACTURER 是否為 “Genymotion”
  • 檢測(cè) Build.PRODUCT 是否為 “sdk”、“sdk_x86”、“vbox86p” 或 “emulator”
  • 檢測(cè) Build.BOARD 是否為 “unknown” 或包含 “android” 或 “droid”
  • 檢測(cè) Build.DEVICE 是否為 “unknown” 或包含 “android” 或 “droid”
  • 檢測(cè) Build.HARDWARE 是否為 “goldfish”、“ranchu” 或包含 “ranchu”
  • 檢測(cè) Build.BRAND 是否以 “generic” 開(kāi)頭,且 Build.DEVICE 以 “generic” 開(kāi)頭
  • 檢測(cè) Build.PRODUCT 是否為 “google_sdk”
  • 檢測(cè)是否存在文件 “/dev/socket/qemud” 或 “/dev/qemu_pipe”
  • 檢測(cè)設(shè)備的電話(huà)號(hào)碼是否為已知的模擬器電話(huà)號(hào)碼

都是基于固件信息的判斷,通過(guò)測(cè)試發(fā)現(xiàn)很多模擬器都失效,參考網(wǎng)上的教程,還有藍(lán)牙、光線(xiàn)傳感器、CPU檢測(cè),配合上面的固件信息,基本可以搞定大部分模擬器。

藍(lán)牙檢測(cè)
public boolean notHasBlueTooth() {

    BluetoothAdapter ba = BluetoothAdapter.getDefaultAdapter();
    if (ba == null) {
        return true;
    } else {
        // 如果有藍(lán)牙不一定是有效的。獲取藍(lán)牙名稱(chēng),若為null 則默認(rèn)為模擬器
        String name = ba.getName();
        if (TextUtils.isEmpty(name)) {
            return true;
        } else {
            return false;
        }
    }
}
光線(xiàn)傳感器檢測(cè)
public static Boolean notHasLightSensorManager(Context context) {
    SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
    Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 
    //光
    if (null == sensor) {
        return true;
    } else {
        return false;
    }
}
CPU檢測(cè)
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;
}

以上檢測(cè)方法也不是完全可行,隨著Android系統(tǒng)的更新,模擬器的增多,需要具體研究對(duì)應(yīng)的一些變動(dòng)來(lái)更新上述代碼。最終判定結(jié)果不一定能檢測(cè)出所有的模擬器,但是一定不能誤殺真機(jī)影響用戶(hù)正常使用。

責(zé)任編輯:武曉燕 來(lái)源: 沐雨花飛蝶
相關(guān)推薦

2017-05-03 14:57:34

2010-01-25 09:28:54

Android模擬器

2010-01-27 13:37:15

2014-06-06 10:32:11

Linux終端模擬器

2010-01-27 18:27:07

Android模擬器應(yīng)

2011-05-24 11:04:58

Android

2013-07-25 14:35:27

2009-09-14 09:59:19

CCNA模擬器介紹CCNA

2011-05-26 13:22:33

電腦上安裝 Android

2010-03-03 17:11:08

2010-01-28 17:18:08

Android模擬器s

2013-07-24 16:08:01

Android模擬器Genymotion

2014-11-17 10:34:15

2013-07-04 13:29:40

Androidgenymotion

2011-05-26 09:40:11

Android模擬器

2012-12-25 12:26:39

2015-07-27 10:38:14

微軟android模擬器

2011-06-07 16:58:42

Android 模擬器

2012-04-10 09:38:57

2013-05-14 10:41:31

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)