Android模拟器检测方法有哪些?

Android模拟器检测方法有哪些?

Android模拟器的检测,一般方法是通过检查设备的一些特征来判断应用是否运行在模拟器。

  1. 检查Build信息:通过读取设备的Build信息来判断是否在模拟器上运行。例如,检查设备的Build.MODEL和Build.MANUFACTURER是否包含常见的模拟器关键词,如”generic”、”sdk”等。

  2. 检查硬件特征:模拟器通常会模拟一些硬件特征,如IMEI、MAC地址等。通过检查这些硬件特征来判断是否在模拟器上运行。

  3. 检查虚拟化指令集:模拟器通常会使用虚拟化指令集来模拟硬件,通过检查CPU的指令集来判断是否在模拟器上运行。

  4. 检查运行环境:通过检查设备的运行环境,如是否有电话功能、GPS功能等来判断是否在模拟器上运行。

这些方法都不是绝对可靠的,模拟器的不断发展可能会绕过这些检测方法。在实际应用中,通过综合多种方法进行检测,以提高准确性。

普遍检测方法

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

以上方法检测模拟器有两个问题:

  1. 拨号检测,Android10.0及以上均为false,Android10.0以上会误判。

  2. Build.SERIAL,Android8.0以上均为unknown导致8.0以上系统均会被误判。

推荐检测方法

设备信息检测
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;
}

上面方法使用了多种方法来检测设备是否为模拟器,包括:

  • 检测 Build.FINGERPRINT 是否以 “generic” 或 “unknown” 开头

  • 检测 Build.MODEL 是否包含 “google_sdk”、“Emulator” 或 “Android SDK built for x86”

  • 检测 Build.MANUFACTURER 是否为 “Genymotion”

  • 检测 Build.PRODUCT 是否为 “sdk”、“sdk_x86”、“vbox86p” 或 “emulator”

  • 检测 Build.BOARD 是否为 “unknown” 或包含 “android” 或 “droid”

  • 检测 Build.DEVICE 是否为 “unknown” 或包含 “android” 或 “droid”

  • 检测 Build.HARDWARE 是否为 “goldfish”、“ranchu” 或包含 “ranchu”

  • 检测 Build.BRAND 是否以 “generic” 开头,且 Build.DEVICE 以 “generic” 开头

  • 检测 Build.PRODUCT 是否为 “google_sdk”

  • 检测是否存在文件 “/dev/socket/qemud” 或 “/dev/qemu_pipe”

  • 检测设备的电话号码是否为已知的模拟器电话号码

都是基于固件信息的判断,通过测试发现很多模拟器都失效,参考网上的教程,还有蓝牙、光线传感器、CPU检测,配合上面的固件信息,基本可以搞定大部分模拟器。

蓝牙检测
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;
        }
    }
}
光线传感器检测
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检测
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;
}

以上检测方法也不是完全可行,随着Android系统的更新,模拟器的增多,需要具体研究对应的一些变动来更新上述代码。最终判定结果不一定能检测出所有的模拟器,但是一定不能误杀真机影响用户正常使用。

<think>好的,我现在要解决用户的问题,用户之前在Android Studio中遇到了模拟器显示“Unavailable on device Pixel API 35”的问题,并且build.gradle里的minSdkVersion和targetSdkVersion都正确。用户现在想检测模拟器的ABI架构支持,并配置以解决这个问题。根据之前的回答和用户提供的引用,我需要整合这些信息,给出具体的步骤。 首先,用户引用了三个来源。引用1提到了APK分片不兼容的问题,指出模拟器支持x86、armeabi-v7a、armeabi,但当前变体没有兼容的ABI。引用2是关于ndk配置的文档位置,引用3则说明需要在build.gradle的ndk中添加x86等架构。之前的回答中,我建议用户添加abiFilters来包含x86_64,但用户现在可能需要更详细的检测和配置方法。 用户现在的问题是,如何检测模拟器的ABI架构,并配置项目以支持它,特别是在遇到Pixel API 35不可用的情况下。已知build.gradle中的minSdk和targetSdk没问题,所以问题应该出在ABI兼容性上。 首先,我需要考虑如何检测模拟器的ABI架构。用户可能需要通过adb命令或者模拟器本身的设置来查看。例如,使用adb shell getprop ro.product.cpu.abi可以获取当前设备的ABI。这应该作为第一步。 接下来,配置项目的ABI支持。根据引用3,用户需要在build.gradle的ndk块中添加对应的架构,比如x86或x86_64。之前的回答中建议添加x86_64,但用户的问题中模拟器可能使用的是x86_64,而项目没有包含,导致APK无法安装。因此,需要指导用户在abiFilters中包含正确的架构。 另外,引用1提到split APKs的问题,可能需要禁用拆分包,或者在build.gradle中配置splits块,指定正确的ABI。不过,如果用户不使用拆分包,可能需要确保所有ABI都包含在同一个APK中,或者在defaultConfig中设置正确的abiFilters。 用户可能还需要检查是否安装了正确的系统镜像。例如,API 35的模拟器可能需要x86_64的系统镜像,而用户可能只安装了arm的,或者项目没有生成对应架构的so文件。因此,需要指导用户检查SDK Manager中的系统镜像,并安装相应的版本。 另外,用户可能需要清理和重建项目,以确保生成的APK包含正确的ABI。之前的回答中提到了清除构建缓存,这可能需要再次强调。 还需要考虑Gradle插件版本是否支持,如果插件版本过旧,可能导致abiFilters配置不被正确处理。根据之前的回答,用户需要更新Gradle插件到7.0以上,并确保Gradle版本兼容。 最后,用户可能需要通过命令行安装APK,并指定abi,以测试是否能够正确安装。例如,使用adb install --abi x86_64来强制安装,这可以帮助确认问题是否出在ABI不匹配。 总结步骤应该是:检测模拟器ABI -> 配置build.gradle中的abiFilters -> 确保系统镜像正确 -> 清理和重建项目 -> 测试安装。此外,需要引用之前的引用,特别是引用3中的配置示例,来指导用户如何修改build.gradle。</think>在Android Studio中检测和配置模拟器的ABI架构支持,可通过以下结构化步骤解决Pixel API 35设备不可用问题: --- ### 一、检测模拟器ABI架构 1. **通过ADB命令直接获取** ```bash adb shell getprop ro.product.cpu.abi # 输出示例:x86_64 adb shell getprop ro.product.cpu.abilist # 列出所有支持的ABI ``` 若输出包含`x86_64`,则模拟器需要该架构支持[^3] 2. **在Android Studio中查看** - 打开模拟器详情页 > **Extended controls** > **Settings** > **Advanced** - 检查"System image ABI"字段(如`Google APIs Intel x86_64`) --- ### 二、配置项目ABI兼容性 1. **修改build.gradle** ```groovy android { defaultConfig { ndk { // 同时包含模拟器架构和项目原生库支持的架构 abiFilters 'armeabi-v7a', 'x86', 'x86_64', 'arm64-v8a' } } // 如果使用splits配置需添加(否则注释掉) splits { abi { enable true reset() include 'x86', 'x86_64' // 明确包含模拟器所需架构 universalApk false } } } ``` 此配置确保APK包含x86_64架构库(API 35模拟器的默认架构)[^1][^3] 2. **验证配置生效** - 构建后检查`app/build/outputs/apk/debug/`目录 - 确认生成的APK文件名包含`x86_64`标识(如`app-x86_64-debug.apk`) --- ### 三、匹配系统镜像与构建环境 1. **安装正确的系统镜像** - 打开**SDK Manager** > **SDK Platforms** - 勾选**Android API 35**并确保安装: - ✅ Android SDK Platform 35 - ✅ Google Play Intel x86_64 System Image 或 **Android Emulator x86_64 System Image** 2. **重建模拟器实例** - 删除旧AVD后新建时选择: - **Target**: Android 13.0 (API 35) - **System Image**: 带`x86_64`标识的镜像 --- ### 四、调试与验证 1. **强制指定ABI安装(命令行验证)** ```bash adb install --abi x86_64 app/build/outputs/apk/debug/app-debug.apk ``` 若输出`Success`则证明ABI配置正确[^1] 2. **检查构建日志** - 在**Build Output**面板搜索关键词: - `Skipped incompatible build` → 原生库架构缺失 - `Generated APK supports ABIs` → 确认包含x86_64 --- ### 五、补充优化措施 ```groovy android { packagingOptions { // 处理多架构库冲突 pickFirst 'lib/x86_64/libnative-lib.so' exclude 'lib/armeabi/**' } } ``` 此配置可解决多ABI构建时的文件冲突问题[^2] --- **典型问题定位表** | 错误现象 | 解决方案 | |---------|----------| | `INSTALL_FAILED_NO_MATCHING_ABIS` | 检查`abiFilters`是否包含模拟器ABI | | `Split APKs incompatible` | 禁用`splits`配置或添加`include 'x86_64'` | | `Native library not found` | 验证NDK编译输出的.so文件架构 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值