安卓判断是否是模拟器,适配主流雷电,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() {@Overridepublic 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

雷电

逍遥

夜神

官方AVD(用这个玩游戏基本没有)

参考 

http://dxtdbj.com/article.php?id=268
https://cloud.tencent.com/developer/article/2019963 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/135408.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp开发小程序中实现骨架屏

第一步&#xff1a;小程序中实现骨架屏在微信开发者工具中点击生成骨架屏&#xff1a; 第二步&#xff1a;复制html代码&#xff0c;到骨架屏vue组件汇中再把之前写的样式代码引入进去&#xff1a; import ../../pages/user/user.css; 第三步&#xff1a;组件中引入骨架屏&am…

【干货】有效削减工厂“隐性”成本的策略

导读 在资源限制条件下&#xff0c;通过企业成本管理提高资源的利用效率&#xff0c;使有限的经济资源生产出更多的产品、创造出更多的价值&#xff0c;达到节约增产的目的&#xff0c;也是企业成本管理的重要目标。通过对大多数企业进行调研&#xff0c;发现企业成本在以下方…

大数据-玩转数据-Flink CEP编程

一、Flink CEP FlinkCEP(Complex event processing for Flink) 是在Flink实现的复杂事件处理库。它可以让你在无界流中检测出特定的数据&#xff0c;有机会掌握数据中重要的那部分。 是一种基于动态环境中事件流的分析技术&#xff0c;事件在这里通常是有意义的状态变化&#…

JDK8源码阅读环境配置

说明 环境 jdk 版本&#xff1a;1.8.0_381 系统&#xff1a;macos 13.5.1 Intel 目的 学习 jdk8 源码&#xff0c;并能自定注释。 新建 java 工程 在 idea 中新建 java 工程&#xff0c;注意并非 maven 工程。如下图&#xff1a;完成后&#xff0c;如下图&#xff1a; 配置…

kali搭建vulhub漏洞靶场

安装kali 下载kali作为虚拟环境&#xff0c; Get Kali | Kali Linux 通过vmvare打开&#xff0c;默认账号密码kali/kali 修改root密码 su passwd root 如果一些配置普通用户做不了就切换kali&#xff0c;或sudo 命令 kali配置 apt换源 echo > /etc/apt/sources.list v…

JS中BigInt的使用

JS中BigInt的使用 BigInt是一种内置对象&#xff0c;它提供了一种方法来表示大于2^53 - 1的整数&#xff0c;通俗来讲就是提供了一种可以表示任意大整数的方法&#xff0c;当我们使用Number来表示一个超过了2 ^53 - 1的整数的时候&#xff0c;会出错。所以此时我们需要使用Big…

LinkedList 源码分析

LinkedList 是一个基于双向链表实现的集合类。 LinkedList 插入和删除元素的时间复杂度 头部插入/删除&#xff1a;只需要修改头结点的指针即可完成插入/删除操作&#xff0c;因此时间复杂度为 O(1)。尾部插入/删除&#xff1a;只需要修改尾结点的指针即可完成插入/删除操作…

STM32的HAL库SPI操作(master 模式)-根据时序图配置SPI

SPI相关基础知识 SPI基本概念请自行百度&#xff0c;参考&#xff1a;百度百科SPI简介.我们讲重点和要注意的地方。 master模式下要关注的地方 接线一一对应 也就是说主控的MISO,MOSI,SCLK,[CSn]分别和设备的MISO,MOSI,SCLK,[CSn]一一对应相连&#xff0c;不交叉&#xff0…

Linux 命令大全(下)

Linux 命令大全&#xff08;上&#xff09; 本文目录 6. 网络通讯 常用命令6.1 ssh 命令 – 安全的远程连接服务器6.1.1 含义6.1.2 语法格式6.1.3 常用参数6.1.4 参考示例 6.2 netstat 命令 – 显示网络状态6.2.1 含义6.2.2 语法格式6.2.3 常用参数6.2.4 参考示例 6.3 dhclient…

爬虫逆向实战(32)-某号店登录(RSA、补环境、混淆)

一、数据接口分析 主页地址&#xff1a;某号店 1、抓包 通过抓包可以发现登录接口是/publicPassport/login.do 2、判断是否有加密参数 请求参数是否加密&#xff1f; 通过查看“载荷”模块可以发现&#xff0c;有三个加密参数&#xff1a;username、password、captchaTok…

swift 问答app

结构体 mvc模式 不变性 试一试

航天航空及国防制造领军企业「同步电子」携手企企通,推进电子制造供应链管理数字化升级

从地球表面到广阔的星空&#xff0c;从近地轨道到深远的太空&#xff0c;中国的航天事业正在以前所未有的速度向前发展。每一次成功的发射&#xff0c;每一次精确的降落&#xff0c;都展现了国人无比的毅力和精湛的技术。而在北斗导航、长征火箭、嫦娥月球探测器等多个航天设备…

vscode 代码高亮显示

很多情况下vscode显示代码无法完全高亮显示&#xff0c;就很不舒服 除了语言设置为pylance之外&#xff0c;vscode本身的主题也是很重要的一个因素 改现代神色即可

Hadoop sqoop

0目录 1.安装sqoop 2.补充sqoop流程 1.安装sqoop 解压、改名 [rootkb129 install]# tar -xvf ./sqoop-1.4.7.tar.gz -C /opt/soft/ [rootkb129 soft]# mv sqoop-1.4.7/ sqoop147 拷贝配置文件 [rootkb129 conf]# pwd /opt/soft/sqoop147/conf [rootkb129 conf]# cp sqoop-en…

Java环境搭建安装IDE

Java环境搭建、安装IDE 文章目录 Java环境搭建、安装IDE1. 下载Java JDK &#xff0c;配置环境变量&#xff0c;在命令行环境下完成hello world程序&#xff1b;简介安装Step 0 安装包准备工作Step 1 下载 Java JDKStep 2 配置环境变量配置 JAVA_HOME配置 Path配置 CLASSPATH S…

巨人互动|Facebook海外户Facebook客户反馈分数

Facebook客户反馈分数是一项用于衡量用户对Facebook产品和服务满意度的指标。该指标被广泛应用于各种调研和评估活动&#xff0c;帮助Facebook了解用户对其平台和功能的意见和建议&#xff0c;并从中识别出改进的机会。 巨人互动|Facebook海外户&Facebook新闻提要的算法&am…

django添加数据库字段进行数据迁移

1.修改view.py里面的变量 2.在model.py新增字段 3.打开terminal并将环境切到项目所在环境&#xff0c;切换方式为 4.执行命令 python manage.py makemigrations backend python manage.py migrate

社区版MyApps低代码平台,免费即刻拥有!

编者按&#xff1a;本文主要介绍了MyApps推出的免费社区版的优势&#xff0c;为企业数字化转型提供了解决方案。立即登录MyApps低代码平台&#xff0c;就能获取永久免费的低代码平台。 1.MyApps社区版的优势 1.1不受限制&#xff0c;畅享自由 无用户限制、无安装限制、全面应用…

使用Cpolar 内网穿透工具,实现公网访问SeaFile搭建的私有云盘

文章目录 1. 前言2. SeaFile云盘设置2.1 Owncould的安装环境设置2.2 SeaFile下载安装2.3 SeaFile的配置 3. cpolar内网穿透3.1 Cpolar下载安装3.2 Cpolar的注册3.3 Cpolar云端设置3.4 Cpolar本地设置 4.公网访问测试5.结语 1. 前言 现在我们身边的只能设备越来越多&#xff0c…

K8S入门前奏之VMware虚拟机网络配置

为了能在本地搭建 K8S 的运行服务器&#xff0c;在个人电脑上安装了虚拟机VMware16版本&#xff0c;并且在阿里巴巴开源镜像站下载了CentOS-7操作系统&#xff1a;阿里巴巴开源镜像站 做完一些列准备工作后&#xff0c;在虚拟机安装完CentOS-7操作系统后&#xff0c;需要对VMw…