安卓判断是否是模拟器,适配主流雷电,MUMU,夜神,逍遥

这篇具有很好参考价值的文章主要介绍了安卓判断是否是模拟器,适配主流雷电,MUMU,夜神,逍遥。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

最近游戏项目组又有新的要求,对于数据上报和数据统计接口,尽可能的具体化,比如是否是模拟器,模拟器的型号,品牌等,都要求统计,后续模拟器玩家在活动发放,安全风控等方面也易于分析和把控。

实现

在网上搜了搜,大概思路是:

1:模拟器的cpu是x86,arm的,通过cpu信息判断

2:模拟器的传感器比较少,尤其没有光传感器等

3:模拟器没有蓝牙模块,可以通过蓝牙判断,这里没有考虑,毕竟需要动态权限

Manifest.permission.BLUETOOTH_CONNECT

在隐私合规的大环境下,还是尽量避免获取多的权限

4:通过部分特征参数,比如Build.FINGERPRINT、 Build.MODEL、Build.BRAND

5:通过模拟器特有文件检测

下面具体贴上工具类代码:

package com.xx.xx.myapplication;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class EmutorUtils {

    private static final String TAG = "EmutorUtils";

    private static final String[] PKG_NAMES = {"com.mumu.launcher", "com.ami.duosupdater.ui", "com.ami.launchmetro",
            "com.ami.syncduosservices", "com.bluestacks.home", "com.bluestacks.windowsfilemanager",
            "com.bluestacks.settings", "com.bluestacks.bluestackslocationprovider", "com.bluestacks.appsettings",
            "com.bluestacks.bstfolder", "com.bluestacks.BstCommandProcessor", "com.bluestacks.s2p", "com.bluestacks.setup",
            "com.bluestacks.appmart", "com.kaopu001.tiantianserver", "com.kpzs.helpercenter", "com.kaopu001.tiantianime",
            "com.android.development_settings", "com.android.development", "com.android.customlocale2", "com.genymotion.superuser",
            "com.genymotion.clipboardproxy", "com.uc.xxzs.keyboard", "com.uc.xxzs", "com.blue.huang17.agent", "com.blue.huang17.launcher",
            "com.blue.huang17.ime", "com.microvirt.guide", "com.microvirt.market", "com.microvirt.memuime", "cn.itools.vm.launcher",
            "cn.itools.vm.proxy", "cn.itools.vm.softkeyboard", "cn.itools.avdmarket", "com.syd.IME", "com.bignox.app.store.hd",
            "com.bignox.launcher", "com.bignox.app.phone", "com.bignox.app.noxservice", "com.android.noxpush", "com.haimawan.push",
            "me.haima.helpcenter", "com.windroy.launcher", "com.windroy.superuser", "com.windroy.launcher", "com.windroy.ime",
            "com.android.flysilkworm", "com.android.emu.inputservice", "com.tiantian.ime", "com.microvirt.launcher", "me.le8.androidassist",
            "com.vphone.helper", "com.vphone.launcher", "com.duoyi.giftcenter.giftcenter"};

    private static final String[] FILES = {"/data/data/com.android.flysilkworm", "/data/data/com.bluestacks.filemanager"};

    public static String checkFeaturesByHardware(Context context) {
        String result = "";
        String hardware = getProperty("ro.hardware");
        if (null == hardware)
            return "unknown";
        String tempValue = hardware.toLowerCase();
        Log.d(TAG,tempValue);
        if(tempValue.startsWith("cancro")){
            result = "MUMU模拟器";
        }else if(tempValue.contains("nox")){
            result = "夜神模拟器";
        }else if(tempValue.equals("android_x86")){
            result= "雷电模拟器";
        }else{
            List pathList = getInstalledSimulatorPackages(context);
            result =  getSimulatorBrand(pathList);
        }
        return result;
    }

    private static String getProperty(String propName) {
        String value = null;
        Object roSecureObj;
        try {
            roSecureObj = Class.forName("android.os.SystemProperties")
                    .getMethod("get", String.class)
                    .invoke(null, propName);
            if (roSecureObj != null) value = (String) roSecureObj;
        } catch (Exception e) {
            value = null;
        } finally {
            return value;
        }
    }


    private static List getInstalledSimulatorPackages(Context context) {
        ArrayList localArrayList = new ArrayList();
        try {
            for (int i = 0; i < PKG_NAMES.length; i++)
                try {
                    context.getPackageManager().getPackageInfo(PKG_NAMES[i], PackageManager.GET_ACTIVITIES);
                    localArrayList.add(PKG_NAMES[i]);
                } catch (PackageManager.NameNotFoundException localNameNotFoundException) {
                }
            if (localArrayList.size() == 0) {
                for (int i = 0; i < FILES.length; i++) {
                    if (new File(FILES[i]).exists())
                        localArrayList.add(FILES[i]);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return localArrayList;
    }

    private static String getSimulatorBrand(List<String> list) {
        if (list.size() == 0)
            return "";
        String pkgName = list.get(0);
        if (pkgName.contains("mumu")) {
            return "mumu";
        } else if (pkgName.contains("ami")) {
            return "AMIDuOS";
        } else if (pkgName.contains("bluestacks")) {
            return "蓝叠";
        } else if (pkgName.contains("kaopu001") || pkgName.contains("tiantian")) {
            return "天天";
        } else if (pkgName.contains("kpzs")) {
            return "靠谱助手";
        } else if (pkgName.contains("genymotion")) {
            if (Build.MODEL.contains("iTools")) {
                return "iTools";
            } else if ((Build.MODEL.contains("ChangWan"))) {
                return "畅玩";
            } else {
                return "genymotion";
            }
        } else if (pkgName.contains("uc")) {
            return "uc";
        } else if (pkgName.contains("blue")) {
            return "blue";
        } else if (pkgName.contains("microvirt")) {
            return "逍遥";
        } else if (pkgName.contains("itools")) {
            return "itools";
        } else if (pkgName.contains("syd")) {
            return "手游岛";
        } else if (pkgName.contains("bignox")) {
            return "夜神";
        } else if (pkgName.contains("haimawan")) {
            return "海马玩";
        } else if (pkgName.contains("windroy")) {
            return "windroy";
        } else if (pkgName.contains("flysilkworm")) {
            return "雷电";
        } else if (pkgName.contains("emu")) {
            return "emu";
        } else if (pkgName.contains("le8")) {
            return "le8";
        } else if (pkgName.contains("vphone")) {
            return "vphone";
        } else if (pkgName.contains("duoyi")) {
            return "多益";
        }
        return "";
    }


    public static boolean isEmulator(Context context){
              return notHasLightSensorManager(context)
                ||isFeatures()
                ||checkIsNotRealPhone()
                ||checkPipes() ||isYeshenEmulator();
    }


    public static String getPhoneBrand(){
        return android.os.Build.BRAND;
    }

    public static String getPhoneModel(){
        return  android.os.Build.MODEL;
    }

    /*
     *用途:判断蓝牙是否有效来判断是否为模拟器
     *返回:true 为模拟器
     */
//    private static 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;
//            }
//        }
//    }

    /*
     *用途:依据是否存在光传感器来判断是否为模拟器
     *返回:true 为模拟器
     */
    private static Boolean notHasLightSensorManager(Context context) {
        SensorManager sensorManager = (SensorManager) context.getSystemService(context.SENSOR_SERVICE);
        Sensor sensor8 = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光
        if (null == sensor8) {
            return true;
        } else {
            return false;
        }
    }

    /*
     *用途:根据部分特征参数设备信息来判断是否为模拟器
     *返回:true 为模拟器
     */
    private 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);
    }

    /*
     *用途:根据CPU是否为电脑来判断是否为模拟器
     *返回:true 为模拟器
     */
    private static boolean checkIsNotRealPhone() {
        String cpuInfo = readCpuInfo();
        if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
            return true;
        }
        return false;
    }

    /*
     *用途:根据CPU是否为电脑来判断是否为模拟器(子方法)
     *返回:String
     */
    private 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;
    }

    /*
     *用途:检测模拟器的特有文件
     *返回:true 为模拟器
     */
    private static String[] known_pipes = {"/dev/socket/qemud", "/dev/qemu_pipe"};
    private static boolean checkPipes() {
        for (int i = 0; i < known_pipes.length; i++) {
            String pipes = known_pipes[i];
            File qemu_socket = new File(pipes);
            if (qemu_socket.exists()) {
                Log.v("Result:", "Find pipes!");
                return true;
            }
        }
        Log.i("Result:", "Not Find pipes!");
        return false;
    }

    //****************适配夜神模拟器*******************
    //获取 cpu 信息
    private static String getCpuInfo() {
        String[] abis = new String[]{};
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            abis = Build.SUPPORTED_ABIS;
        } else {
            abis = new String[]{Build.CPU_ABI, Build.CPU_ABI2};
        }
        StringBuilder abiStr = new StringBuilder();
        for (String abi : abis) {
            abiStr.append(abi);
            abiStr.append(',');
        }

        return abiStr.toString();
    }

    // 通过cpu判断是否模拟器 ,适配夜神
    private static boolean isYeshenEmulator() {
        String abiStr = getCpuInfo();
        if (abiStr != null && abiStr.length() > 0) {
            boolean isSupportX86 = false;
            boolean isSupportArm = false;

            if (abiStr.contains("x86_64") || abiStr.contains("x86")) {
                isSupportX86 = true;
            }
            if (abiStr.contains("armeabi") || abiStr.contains("armeabi-v7a") || abiStr.contains("arm64-v8a")) {
                isSupportArm = true;
            }
            if (isSupportX86 && isSupportArm) {
                //同时拥有X86和arm的判断为模拟器。
                return true;
            }
        }
        return false;
    }


}

使用

boolean flag = EmutorUtils.isEmulator(MainActivity.this);
        Toast.makeText(MainActivity.this,"是否是模拟器:"+flag,Toast.LENGTH_SHORT).show();

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = EmutorUtils.checkFeaturesByHardware(MainActivity.this);
                String brand = EmutorUtils.getPhoneBrand();
                String model = EmutorUtils.getPhoneModel();
                String result = "name:"+name+"brand:"+brand+"model:"+model;
                Toast.makeText(MainActivity.this,result,Toast.LENGTH_SHORT).show();
            }
        });

效果图

mumu

android 判断模拟器,Android工具类,android

雷电

android 判断模拟器,Android工具类,android逍遥

android 判断模拟器,Android工具类,android

夜神

android 判断模拟器,Android工具类,android官方AVD(用这个玩游戏基本没有)

android 判断模拟器,Android工具类,android

参考 

http://dxtdbj.com/article.php?id=268
https://cloud.tencent.com/developer/article/2019963 文章来源地址https://www.toymoban.com/news/detail-752097.html

到了这里,关于安卓判断是否是模拟器,适配主流雷电,MUMU,夜神,逍遥的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • fiddler抓包 雷电模拟器9(安卓9.0)教程,app加载不出来要记得移动证书目录

    使用的是网上的fiddler中文汉化版,按照百度搜索的教程总是有一些坑,记录一下。 1、 设置https ,在捕获https这边勾上三个√,点击【动作】,生成证书,导到桌面。  2、 设置连接 ,允许远程计算机连接,勾上√,记住端口数字,这边我是8888  3、在fiddler右侧或ipconfig中查

    2024年01月16日
    浏览(100)
  • fiddler+安卓雷电模拟器+解决无法抓包问题,看我就对了,一站式解决问题,告别到处搜文章

    前言:本文讲述fiddler抓取模拟器中数据包,话不多说来看正文。 目录 环境准备:雷电模拟器、fiddler、adb adb和fiddler下载地址:  一、Fiddler设置 1.HTTPS:解密https流量、忽略不安全证书 2.连接设置:允许远程计算机连接  3.根证书安装:导出桌面安装证书  二、模拟器设置 1

    2024年02月09日
    浏览(86)
  • 适配m1芯片的安卓手机模拟器来了

    最近在学习ADB,手里没有安卓机,一些比较火的像夜神、MUMU模拟器在M1电脑上不适用,终于在我不懈的努力下,找到了可以使用的安卓模拟器,话不多说,上操作! 打开GitHub,搜索 m1 Android 点击第☝️个 - google/android-emulator-m1-preview 点击右边的 Releases 一共3个版本,选择最新

    2024年02月11日
    浏览(93)
  • 雷电模拟器端口号 adb连接

    在尝试adb连接雷电模拟器时,网上查询了一下端口号,发现说是5555. 但是自己尝试,会提示: cannot connect to 127.0.0.1:5555: 由于目标计算机积极拒绝,无法连接。 (10061) 终于发现,因为我打开的模拟器,编号已经到了29。。。 此时的端口号就不是5555了, 而是5555+2*29=5613。(即 端

    2024年02月05日
    浏览(42)
  • Python - 控制雷电模拟器(Dnconsole)

    1.Dnconsole控制台 雷电模拟器9.0 雷电模拟器9.0 ,32+64位并行,支持对画质、性能要求较高的一类游戏。关于使用Python实现雷电模拟器的控制代码,主要适用于雷电模拟器9.0版本。不同的模拟器版本的控制台程序命名也不同(9.0版本为“ldconsole.exe”),可以使用的指令也不同,

    2023年04月08日
    浏览(26)
  • Fiddler+雷电模拟器APP抓包

    因为工作中涉及到移动端的内容相对较多,在需要接口文档时,开发人员无法立即提供,因此需要我们自己使用对APP进行抓包,完成相关的测试工作。 1、打开Fiddler客户端,依次进入Tools—options设置,先点击Connections设置,选择Allowremote computers to connect,确认监听端口为8888。

    2024年02月12日
    浏览(33)
  • android studio连接雷电模拟器调试

    一、下载雷电模拟器,安装完成后打开 下载地址:https://www.ldmnq.com/ 二、进入模拟器的桌面,系统应用—打开设置—点击关于平板电脑,连续点击5次版本号–会出现开发者选项—-进入开发者选项—-勾选usb调试。 三:按win+r,输入cmd打开命令控制器,将目录切换到你安装雷电

    2023年04月08日
    浏览(35)
  • vmare 虚拟机上安装雷电模拟器的解决

    自已有一个需求:需要在虚拟机,需要在上面安装一下模拟器3.0; 环境: vmare老版本:6.0~7.0 虚拟机系统:windows7 旗舰版 64位 遇到问题: 1. 没有开启VT-x。 分析:原来的vmare是低版本好像是 vmare7;没有Intel VT-x选项选择。 我的解决方法: 升级vmare为Vmware Workstation 16 Pro; 把当

    2024年02月06日
    浏览(74)
  • 雷电9模拟器安装magisk和lsposed

    之前一直用真机搭建测试环境,今天看到正己大佬的 《安卓逆向这档事》之模拟器环境搭建 视频教程,看到其中推荐了 适用于几乎所有安卓模拟器(7+)安装magisk的教程-简单无脑向 这个教程,其实之前就看过这个大佬的教程,无奈我的模拟器版本可能不对,一直安装不成功,

    2024年02月02日
    浏览(42)
  • 移动应用测试(Python+Appium+雷电模拟器)

    一、node.js(v20.1.1) 二、Java(JDK17) 三、Android SDK(24.4.1版本) 四、Python(3.10) 五、PyCharm(2023.3.2) 六、Appium(1.21.0) 七、雷电模拟器(雷电9) 若不想单独去下载,想直接获取所有安装包,请访问百度网盘链接提取:https://pan.baidu.com/s/1LSzazfQ2PbdiMLfZ4WiWAQ?pwd=n4vi        在

    2024年03月16日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包