如何不讓你的APP在模擬器中運行。

不讓APP在模擬器運行在特殊的需求下還是要做一個的。

首先你需要一個這樣的工具類。
public class FindEmulator {

    // Need to check the format of these
    // Android emulator support up to 16 concurrent emulator
    // The console of the first emulator instance running on a given
    // machine uses console port 5554
    // Subsequent instances use port numbers increasing by two
    private String[] known_numbers = {
            "15555215554", // Default emulator phone numbers + VirusTotal
            "15555215556", "15555215558", "15555215560", "15555215562", "15555215564",
            "15555215566",
            "15555215568", "15555215570", "15555215572", "15555215574", "15555215576",
            "15555215578",
            "15555215580", "15555215582", "15555215584",};
    private String[] known_device_ids = {"000000000000000", // Default emulator id
            "e21833235b6eef10", // VirusTotal id
            "012345678912345"};
    private String[] known_imsi_ids = {"310260000000000" // Default imsi id
    };
    private String[] known_serial_number = {"89014103211118510720"};

    private String[] known_pipes = {"/dev/socket/qemud", "/dev/qemu_pipe"};
    private String[] known_files = {"/system/lib/libc_malloc_debug_qemu.so",
            "/sys/qemu_trace"};
//            "/system/bin/qemu-props"}; SM-G3502I GT-I9308 有此文件
    private String[] known_geny_files = {"/dev/socket/genyd", "/dev/socket/baseband_genyd"};
    private String[] known_qemu_drivers = {"goldfish"};

    /**
     * Known props, in the format of [property name, value to seek] if value to seek is null, then
     * it is assumed that the existence of this property (anything not null) indicates the QEmu
     * environment.
     */
    private Property[] known_props = {new Property("init.svc.qemud", null),
            new Property("init.svc.qemu-props", null), new Property("qemu.hw.mainkeys", null),
            new Property("qemu.sf.fake_camera", null), new Property("qemu.sf.lcd_density", null),
            new Property("ro.bootloader", "unknown"), new Property("ro.bootmode", "unknown"),
            new Property("ro.hardware", "goldfish"), new Property("ro.kernel.android.qemud", null),
            new Property("ro.kernel.qemu.gles", null), new Property("ro.kernel.qemu", "1"),
            new Property("ro.product.device", "generic"), new Property("ro.product.model", "sdk"),
            new Property("ro.product.name", "sdk"),
            // Need to double check that an "empty" string ("") returns null
            new Property("ro.serialno", null)};

    private TelephonyManager mTM = null;
    private final Context mContext;

    public FindEmulator(Context context) {
        mContext = context.getApplicationContext();
    }

    /**
     * Check the existence of known pipes used by the Android QEmu environment.
     *
     * @return {@code true} if any pipes where found to exist or {@code false} if not.
     */
    public boolean hasPipes() {
        for (String pipe : known_pipes) {
            File qemu_socket = new File(pipe);
            if (qemu_socket.exists()) {
                return true;
            }
        }

        return false;
    }

    public String getFirstExistsPipe() {
        for (String pipe : known_pipes) {
            File qemu_socket = new File(pipe);
            if (qemu_socket.exists()) {
                return pipe;
            }
        }

        return null;
    }

    /**
     * Check the existence of known files used by the Android QEmu environment.
     *
     * @return {@code true} if any files where found to exist or {@code false} if not.
     */
    public boolean hasQEmuFiles() {
        for (String pipe : known_files) {
            File qemu_file = new File(pipe);
            if (qemu_file.exists()) {
                return true;
            }
        }

        return false;
    }

    public String getFirstExistsQEmuFile() {
        for (String file : known_files) {
            File geny_file = new File(file);
            if (geny_file.exists()) {
                return file;
            }
        }

        return null;
    }

    /**
     * Check the existence of known files used by the Genymotion environment.
     *
     * @return {@code true} if any files where found to exist or {@code false} if not.
     */
    public boolean hasGenyFiles() {
        for (String file : known_geny_files) {
            File geny_file = new File(file);
            if (geny_file.exists()) {
                return true;
            }
        }

        return false;
    }

    public String getFirstExistsGenyFile() {
        for (String file : known_geny_files) {
            File geny_file = new File(file);
            if (geny_file.exists()) {
                return file;
            }
        }

        return null;
    }

    /**
     * Reads in the driver file, then checks a list for known QEmu drivers.
     *
     * @return {@code true} if any known drivers where found to exist or {@code false} if not.
     */
    public boolean hasQEmuDrivers() {
        for (File drivers_file : new File[] {new File("/proc/tty/drivers"),
                new File("/proc/cpuinfo")}) {
            if (drivers_file.exists() && drivers_file.canRead()) {
                // We don't care to read much past things since info we care about should be
                // inside here
                byte[] data = new byte[1024];
                try {
                    InputStream is = new FileInputStream(drivers_file);
                    is.read(data);
                    is.close();
                } catch (Exception exception) {
                    exception.printStackTrace();
                }

                String driver_data = new String(data);
                for (String known_qemu_driver : known_qemu_drivers) {
                    if (driver_data.contains(known_qemu_driver)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }

    public String getFristQEmuDriver() {
        for (File drivers_file : new File[] {new File("/proc/tty/drivers"),
                new File("/proc/cpuinfo")}) {
            if (drivers_file.exists() && drivers_file.canRead()) {
                // We don't care to read much past things since info we care about should be
                // inside here
                byte[] data = new byte[1024];
                try {
                    InputStream is = new FileInputStream(drivers_file);
                    is.read(data);
                    is.close();
                } catch (Exception exception) {
                    exception.printStackTrace();
                }

                String driver_data = new String(data);
                for (String known_qemu_driver : known_qemu_drivers) {
                    if (driver_data.contains(known_qemu_driver)) {
                        return known_qemu_driver;
                    }
                }
            }
        }

        return null;
    }

    public String getSerialNumber() {
        if (null == mTM) {
            mTM = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        }
        return mTM.getSimSerialNumber();
    }

    public boolean hasKnownSerialNumber() {
        String phoneNumber = getSerialNumber();

        for (String number : known_serial_number) {
            if (number.equalsIgnoreCase(phoneNumber)) {
                return true;
            }

        }
        return false;
    }

    public String getPhoneNumber() {
        if (null == mTM) {
            mTM = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        }
        return mTM.getLine1Number();
    }

    public boolean hasKnownPhoneNumber() {
        String phoneNumber = getPhoneNumber();

        for (String number : known_numbers) {
            if (number.equalsIgnoreCase(phoneNumber)) {
                return true;
            }

        }
        return false;
    }

    public String getDeviceId() {
        if (null == mTM) {
            mTM = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        }
        return mTM.getDeviceId();
    }

    public boolean hasKnownDeviceId() {
        String deviceId = getDeviceId();

        for (String known_deviceId : known_device_ids) {
            if (known_deviceId.equalsIgnoreCase(deviceId)) {
                return true;
            }
        }
        return false;
    }

    public String getImsi() {
        if (null == mTM) {
            mTM = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
        }
        return mTM.getSubscriberId();
    }

    public boolean hasKnownImsi() {
        String imsi = getImsi();
        for (String known_imsi : known_imsi_ids) {
            if (known_imsi.equalsIgnoreCase(imsi)) {
                return true;
            }
        }
        return false;
    }

    public boolean hasEmulatorBuild() {
        // String BOARD = Build.BOARD;  Coolpad 8298-A01 The name of the underlying board, like "unknown".
        // This appears to occur often on real hardware... that's sad
        // String BOOTLOADER = android.os.Build.BOOTLOADER; // The system bootloader version number.
        String BRAND = Build.BRAND; // The brand (e.g., carrier) the software is customized
        // for, if any.
        // "generic"
        String DEVICE = Build.DEVICE; // The name of the industrial design. "generic"
        String HARDWARE = Build.HARDWARE; // The name of the hardware (from the kernel command
        // line or
        // /proc). "goldfish"
        String MODEL = Build.MODEL; // The end-user-visible name for the end product. "sdk"
        String PRODUCT = Build.PRODUCT; // The name of the overall product.
        if ((BRAND.compareTo("generic") == 0) || (DEVICE.compareTo("generic") == 0)
                || (MODEL.compareTo("sdk") == 0) || (PRODUCT.compareTo("sdk") == 0)
                || (HARDWARE.compareTo("goldfish") == 0)) {
            return true;
        }
        return false;
    }

    public String getOperatorName() {
        if (null == mTM) {
            mTM = ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE));
        }
        return mTM.getNetworkOperatorName();
    }

    public boolean isOperatorNameAndroid() {
        String szOperatorName = getOperatorName();
        return szOperatorName.equalsIgnoreCase("android");
    }

    /**
     * Will query specific system properties to try and fingerprint a QEmu environment. A minimum
     * threshold must be met in order to prevent false positives.
     *
     * @return {@code true} if enough properties where found to exist or {@code false} if not.
     */
    public boolean hasQEmuProps() {
        int found_props = 0;

        for (Property property : known_props) {
            String property_value = getProp(mContext, property.name);
            // See if we expected just a non-null
            if (TextUtils.isEmpty(property.seek_value) && !TextUtils.isEmpty(property_value)) {
                found_props++;
            } else if (!TextUtils.isEmpty(property.seek_value) && !TextUtils.isEmpty(property_value) &&
                        (property_value.contains(property.seek_value))) {
                // See if we expected a value to seek
                found_props++;
            }
        }

        /*
      The "known" props have the potential for false-positiving due to interesting (see: poorly)
      made Chinese devices/odd ROMs. Keeping this threshold low will result in better QEmu
      detection with possible side affects.
     */
        if (found_props >= 5) {
            return true;
        }

        return false;
    }

    public String getQEmuProps() {
        String ret = "";
        for (Property property : known_props) {
            String property_value = getProp(mContext, property.name);
            // See if we expected just a non-null
            if (TextUtils.isEmpty(property.seek_value) && !TextUtils.isEmpty(property_value)) {
                ret += property.name + ":" + property_value + "\n";
            } else if (!TextUtils.isEmpty(property.seek_value) && !TextUtils.isEmpty(property_value) &&
                        (property_value.contains(property.seek_value))) {
                // See if we expected a value to seek
                ret += property.name + ":" + property_value + "\n";
            }
        }

        return ret;
    }

    /**
     * Method to reflectively invoke the SystemProperties.get command - which is the equivalent to
     * the adb shell getProp command.
     *
     * @param context
     *         A {@link Context} object used to get the proper ClassLoader (just needs to be
     *         Application Context object)
     * @param property
     *         A {@code String} object for the property to retrieve.
     *
     * @return {@code String} value of the property requested.
     */
    public String getProp(Context context, String property) {
        try {
            ClassLoader classLoader = context.getClassLoader();
            Class<?> systemProperties = classLoader.loadClass("android.os.SystemProperties");

            Method get = systemProperties.getMethod("get", String.class);

            Object[] params = new Object[1];
            params[0] = new String(property);

            return (String) get.invoke(systemProperties, params);
        } catch (IllegalArgumentException iAE) {
            throw iAE;
        } catch (Exception exception) {
            throw null;
        }
    }

    public static class Property {
        public String name;
        public String seek_value;

        public Property(String name, String seek_value) {
            this.name = name;
            this.seek_value = seek_value;
        }
    }

}

接下來你需要在你的主啓動Activity裏寫這麼一個方法:

private void isEmulator(){
    FindEmulator emulator = new FindEmulator(this);
    boolean isEmulator = false;
    String detailStr = "";
    if (emulator.hasEmulatorBuild()) {
        isEmulator = true;
        detailStr =
            "Brand: " + Build.BRAND + "\n" +
            "Device: " + Build.DEVICE + "\n" +
            "Hardware: " + Build.HARDWARE + "\n" +
            "Product: " + Build.PRODUCT + "\n" +
            "Serial: " + Build.SERIAL + "\n" +
            "Model: " + Build.MODEL + "\n";
    } else if (emulator.hasKnownDeviceId()) {
        isEmulator = true;
        detailStr = "getDeviceId: " + emulator.getDeviceId();
    } else if (emulator.hasKnownImsi()) {
        isEmulator = true;
        detailStr = "getImsi: " + emulator.getImsi();
    } else if (emulator.hasKnownPhoneNumber()) {
        isEmulator = true;
        detailStr = "getPhoneNumber: " + emulator.getPhoneNumber();
    } else if (emulator.hasKnownSerialNumber()) {
        isEmulator = true;
        detailStr = "getSerialNumber: " + emulator.getSerialNumber();
    } else if (emulator.hasPipes()) {
        isEmulator = true;
        detailStr = "hasPipes: " + emulator.getFirstExistsPipe();
    } else if (emulator.hasGenyFiles()) {
        isEmulator = true;
        detailStr = "hasGenyFiles: " + emulator.getFirstExistsGenyFile();
    } else if (emulator.hasQEmuDrivers()) {
        isEmulator = true;
        detailStr = "hasQEmuDrivers: " + emulator.getFristQEmuDriver();
    } else if (emulator.hasQEmuProps()) {
        isEmulator = true;
        detailStr = "hasQEmuProps: " + emulator.getQEmuProps();
    } else if (emulator.isOperatorNameAndroid()) {
        isEmulator = true;
        detailStr = "operatorNameAndroid: " + emulator.getOperatorName();
    }

    if (isEmulator) {
        mHandler.obtainMessage(MSG_IS_EMULATOR, "模擬器安裝退出異常:"+detailStr).sendToTarget();
        }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章