ToB企服应用市场:ToB评测及商务社交产业平台

标题: 安全风险 - 检测设备是否为模仿器 [打印本页]

作者: 卖不甜枣    时间: 2024-7-25 15:40
标题: 安全风险 - 检测设备是否为模仿器
在很多安全机构的检测中,关于模仿器的运行环境一般也会做监听处理,有的大概答应实行但是会提示用户,有的大概直接克制在模仿器上运行我方APP
  怎样判定当前 app 是运行在Android真机,还是运行在模仿器? 大概做 Framework 的朋友头脑会更开阔一些,不过现在也可以跟我这门外汉一起来轻微相识下

  
攻略过程

   其实我已经很久没有效过模仿器了,不过可以肯定的是模仿器与真机的本质区别大概率在于运行载体
  Android 有非常多的模仿器,我已知的有官方自带的 Genymotion 模仿器,三方平台的夜神模仿器、天天模仿器等,以是想要完全鉴别出设备的运行环境,其实应该是存在肯定题目的,我们只能说尽大概保证肯定的容错率(我有想过很多应用平台提供的云机,但好像大多提供的都是真机,以是此项不在思量范围之内)
基础思考

以下的一些思考紧张结合了 怎样判定是否是模仿器还是真机、全面检测设备是否模仿器、一行代码帮你检测Android模仿器、安卓逆向环境检测–模仿器 等多篇新旧文章

模仿器的 IMEI 可以修改,早期平板大概没有IMEI,但是随着时代发展很多平板设备已拥有了属于本身的IMEI

模仿器的MAC地址是固定的几种,但是这些固定的地址随着模仿器类型递增,没有找到合适的,同时mac地址现在可以被模仿…

因为调用结果可以容易被修改,好比直接修改Android的源代码或者借助 Xposed Framework 举行修改(这种场景我虽未到场,但是应该可以参考Java的反射机制)

  1. public boolean isSimulator1() {
  2.         String url = "tel:" + "10086";
  3.         Intent intent = new Intent();
  4.         intent.setData(Uri.parse(url));
  5.         intent.setAction(Intent.ACTION_DIAL);
  6.         // 是否可以处理跳转到拨号的 Intent
  7.         boolean canResolveIntent = intent.resolveActivity(mContext.getPackageManager()) != null;
  8.                 return !canResolveIntent;
  9. }
复制代码

涉及到敏感权限时需要申请权限,根据授权结果容易出现误判,同时影响用户体验
  1.     private static String[]known_numbers = {"15555215554","15555215556",
  2.             "15555215558","15555215560","15555215562","15555215564",
  3.             "15555215566","15555215568","15555215570","15555215572",
  4.             "15555215574","15555215576","15555215578","15555215580",
  5.             "15555215582","15555215584",};
  6.     public static Boolean CheckPhoneNumber(Context context){
  7.         TelephonyManager telephonyManager =(TelephonyManager)context
  8.                 .getSystemService(Context.TELEPHONY_SERVICE);
  9.         String phonenumber =telephonyManager.getLine1Number();
  10.         for(String number :known_numbers){
  11.             if(number.equalsIgnoreCase(phonenumber)){
  12.                 Log.v("Result:","Find PhoneNumber!");
  13.                 return true;
  14.             }
  15.         }
  16.         Log.v("Result:","Not Find PhoneNumber!");
  17.         return false;
  18.     }
复制代码
特有文件检测 - 权限要求

设备IDS检测 - 权限要求


  1. public static boolean checkIsNotRealPhone() {
  2.     String cpuInfo = readCpuInfo();
  3.     if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) {
  4.         return true;
  5.     }
  6.     return false;
  7. }
  8. public static String readCpuInfo() {
  9.     String result = "";
  10.     try {
  11.         String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
  12.         ProcessBuilder cmd = new ProcessBuilder(args);
  13.         Process process = cmd.start();
  14.         StringBuffer sb = new StringBuffer();
  15.         String readLine = "";
  16.         BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
  17.         while ((readLine = responseReader.readLine()) != null) {
  18.             sb.append(readLine);
  19.         }
  20.         responseReader.close();
  21.         result = sb.toString().toLowerCase();
  22.     } catch (IOException ex) {
  23.     }
  24.     return result;
  25. }
复制代码
进阶思考

在一篇Blog内有看到这样一副图,值得借鉴,因为我末了使用的 easyprotector 框架就做了硬件信息检测

Tip:有爱好的可以参考以下方法扩展 easyprotector 框架内的模仿器检测部分
模仿器框架文件
  1. UNEXPORT void AntiEmulator::check_file() {
  2.     char *(path[]) = {
  3.             "/system/bin/androVM-prop",   //检测androidVM
  4.             "/system/bin/microvirt-prop", //检测逍遥模拟器--新版本找不到特征
  5.             "/system/lib/libdroid4x.so",  //检测海马模拟器
  6.             "/system/bin/windroyed",      //检测文卓爷模拟器
  7.             "/system/bin/nox-prop",       //检测夜神模拟器--某些版本找不到特征
  8.             "/system/lib/libnoxspeedup.so",//检测夜神模拟器
  9.             "/system/bin/ttVM-prop",      //检测天天模拟器
  10.             "/data/.bluestacks.prop",     //检测bluestacks模拟器  51模拟器
  11.             "/system/bin/duosconfig",     //检测AMIDuOS模拟器
  12.             "/system/etc/xxzs_prop.sh",   //检测星星模拟器
  13.             "/system/etc/mumu-configs/device-prop-configs/mumu.config", //网易MuMu模拟器
  14.             "/system/priv-app/ldAppStore",   //雷电模拟器
  15.             "/system/bin/ldinit",             //雷电模拟器
  16.             "/system/bin/ldmountsf",          //雷电模拟器
  17.             "/system/app/AntStore",          //小蚁模拟器
  18.             "/system/app/AntLauncher",       //小蚁模拟器
  19.             "vmos.prop",                     //vmos虚拟机
  20.             "fstab.titan",                   //光速虚拟机
  21.             "init.titan.rc",                 //光速虚拟机
  22.             "x8.prop",                       //x8沙箱和51虚拟机
  23.             "/system/lib/libc_malloc_debug_qemu.so", //AVD QEMU
  24.             "/system/bin/microvirtd",
  25.             "/dev/socket/qemud",
  26.             "/dev/qemu_pipe"};
  27.     for (int i = 0; i < sizeof(path) / sizeof(char*); i++){
  28.         if (Syscall::check_file_or_dir_exists(path[i])){
  29.             LOGI("check_file  %s file existing", path[i]);
  30.             // TODO 风险
  31.         }
  32.     }
  33. }
复制代码

easyprotector 框架剖析

   关于 easyprotector框架 文档可以参考 一行代码帮你检测Android模仿器(更新至1.1.0) 会更详细一些
  我之以是在 github 选这个框架,紧张有几点原因

直接通过框架源码,检察下模仿器检测的实行过程


   源码中 ro.build、ro.product、gsm.version 含义,做Framework朋友大概比力相识,紧张用于检测一些体系级信息
  

之前有提到功能扩展和延伸,各人可自行在该类源码中举行扩展,不过最好另起方法,有自信的话改原方法也行


剥离 easyprotector框架 模仿器检测功能

因为 easyprotector框架 中涉及的功能比力多,我习惯性只抽出了我所需要的部分
CommandUtil (公共、基础)

简单来看紧张是通过反射机制获取一些体系的公共资源信息
  1. import java.io.BufferedInputStream;
  2. import java.io.BufferedOutputStream;
  3. import java.io.IOException;
  4. /**
  5. * Project Name:EasyProtector
  6. * Package Name:com.lahm.library
  7. * Created by lahm on 2018/6/8 16:23 .
  8. */
  9. public class CommandUtil {
  10.     private CommandUtil() {
  11.     }
  12.     private static class SingletonHolder {
  13.         private static final CommandUtil INSTANCE = new CommandUtil();
  14.     }
  15.     public static final CommandUtil getSingleInstance() {
  16.         return SingletonHolder.INSTANCE;
  17.     }
  18.     public String getProperty(String propName) {
  19.         String value = null;
  20.         Object roSecureObj;
  21.         try {
  22.             roSecureObj = Class.forName("android.os.SystemProperties")
  23.                     .getMethod("get", String.class)
  24.                     .invoke(null, propName);
  25.             if (roSecureObj != null) value = (String) roSecureObj;
  26.         } catch (Exception e) {
  27.             value = null;
  28.         } finally {
  29.             return value;
  30.         }
  31.     }
  32.     public String exec(String command) {
  33.         BufferedOutputStream bufferedOutputStream = null;
  34.         BufferedInputStream bufferedInputStream = null;
  35.         Process process = null;
  36.         try {
  37.             process = Runtime.getRuntime().exec("sh");
  38.             bufferedOutputStream = new BufferedOutputStream(process.getOutputStream());
  39.             bufferedInputStream = new BufferedInputStream(process.getInputStream());
  40.             bufferedOutputStream.write(command.getBytes());
  41.             bufferedOutputStream.write('\n');
  42.             bufferedOutputStream.flush();
  43.             bufferedOutputStream.close();
  44.             process.waitFor();
  45.             String outputStr = getStrFromBufferInputSteam(bufferedInputStream);
  46.             return outputStr;
  47.         } catch (Exception e) {
  48.             return null;
  49.         } finally {
  50.             if (bufferedOutputStream != null) {
  51.                 try {
  52.                     bufferedOutputStream.close();
  53.                 } catch (IOException e) {
  54.                     e.printStackTrace();
  55.                 }
  56.             }
  57.             if (bufferedInputStream != null) {
  58.                 try {
  59.                     bufferedInputStream.close();
  60.                 } catch (IOException e) {
  61.                     e.printStackTrace();
  62.                 }
  63.             }
  64.             if (process != null) {
  65.                 process.destroy();
  66.             }
  67.         }
  68.     }
  69.     private static String getStrFromBufferInputSteam(BufferedInputStream bufferedInputStream) {
  70.         if (null == bufferedInputStream) {
  71.             return "";
  72.         }
  73.         int BUFFER_SIZE = 512;
  74.         byte[] buffer = new byte[BUFFER_SIZE];
  75.         StringBuilder result = new StringBuilder();
  76.         try {
  77.             while (true) {
  78.                 int read = bufferedInputStream.read(buffer);
  79.                 if (read > 0) {
  80.                     result.append(new String(buffer, 0, read));
  81.                 }
  82.                 if (read < BUFFER_SIZE) {
  83.                     break;
  84.                 }
  85.             }
  86.         } catch (Exception e) {
  87.             e.printStackTrace();
  88.         }
  89.         return result.toString();
  90.     }
  91. }
复制代码
EmulatorCheckUtil (核心)

  1. import android.content.Context;
  2. import android.content.pm.PackageManager;
  3. import android.hardware.Sensor;
  4. import android.hardware.SensorManager;
  5. import android.text.TextUtils;
  6. import static android.content.Context.SENSOR_SERVICE;
  7. import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_EMULATOR;
  8. import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_MAYBE_EMULATOR;
  9. import static cn.com.huaan.fund.acts.base.safe.CheckResult.RESULT_UNKNOWN;
  10. /**
  11. * Project Name:EasyProtector
  12. * Package Name:com.lahm.library
  13. * Created by lahm on 2018/6/8 15:01 .
  14. */
  15. public class EmulatorCheckUtil {
  16.     private EmulatorCheckUtil() {
  17.     }
  18.     private static class SingletonHolder {
  19.         private static final EmulatorCheckUtil INSTANCE = new EmulatorCheckUtil();
  20.     }
  21.     public static final EmulatorCheckUtil getSingleInstance() {
  22.         return SingletonHolder.INSTANCE;
  23.     }
  24.     public boolean readSysProperty(Context context, EmulatorCheckCallback callback) {
  25.         if (context == null)
  26.             throw new IllegalArgumentException("context must not be null");
  27.         int suspectCount = 0;
  28.         //检测硬件名称
  29.         CheckResult hardwareResult = checkFeaturesByHardware();
  30.         switch (hardwareResult.result) {
  31.             case RESULT_MAYBE_EMULATOR:
  32.                 ++suspectCount;
  33.                 break;
  34.             case RESULT_EMULATOR:
  35.                 if (callback != null) callback.findEmulator("hardware = " + hardwareResult.value);
  36.                 return true;
  37.         }
  38.         //检测渠道
  39.         CheckResult flavorResult = checkFeaturesByFlavor();
  40.         switch (flavorResult.result) {
  41.             case RESULT_MAYBE_EMULATOR:
  42.                 ++suspectCount;
  43.                 break;
  44.             case RESULT_EMULATOR:
  45.                 if (callback != null) callback.findEmulator("flavor = " + flavorResult.value);
  46.                 return true;
  47.         }
  48.         //检测设备型号
  49.         CheckResult modelResult = checkFeaturesByModel();
  50.         switch (modelResult.result) {
  51.             case RESULT_MAYBE_EMULATOR:
  52.                 ++suspectCount;
  53.                 break;
  54.             case RESULT_EMULATOR:
  55.                 if (callback != null) callback.findEmulator("model = " + modelResult.value);
  56.                 return true;
  57.         }
  58.         //检测硬件制造商
  59.         CheckResult manufacturerResult = checkFeaturesByManufacturer();
  60.         switch (manufacturerResult.result) {
  61.             case RESULT_MAYBE_EMULATOR:
  62.                 ++suspectCount;
  63.                 break;
  64.             case RESULT_EMULATOR:
  65.                 if (callback != null)
  66.                     callback.findEmulator("manufacturer = " + manufacturerResult.value);
  67.                 return true;
  68.         }
  69.         //检测主板名称
  70.         CheckResult boardResult = checkFeaturesByBoard();
  71.         switch (boardResult.result) {
  72.             case RESULT_MAYBE_EMULATOR:
  73.                 ++suspectCount;
  74.                 break;
  75.             case RESULT_EMULATOR:
  76.                 if (callback != null) callback.findEmulator("board = " + boardResult.value);
  77.                 return true;
  78.         }
  79.         //检测主板平台
  80.         CheckResult platformResult = checkFeaturesByPlatform();
  81.         switch (platformResult.result) {
  82.             case RESULT_MAYBE_EMULATOR:
  83.                 ++suspectCount;
  84.                 break;
  85.             case RESULT_EMULATOR:
  86.                 if (callback != null) callback.findEmulator("platform = " + platformResult.value);
  87.                 return true;
  88.         }
  89.         //检测基带信息
  90.         CheckResult baseBandResult = checkFeaturesByBaseBand();
  91.         switch (baseBandResult.result) {
  92.             case RESULT_MAYBE_EMULATOR:
  93.                 suspectCount += 2;//模拟器基带信息为null的情况概率相当大
  94.                 break;
  95.             case RESULT_EMULATOR:
  96.                 if (callback != null) callback.findEmulator("baseBand = " + baseBandResult.value);
  97.                 return true;
  98.         }
  99.         //检测传感器数量
  100.         int sensorNumber = getSensorNumber(context);
  101.         if (sensorNumber <= 7) ++suspectCount;
  102.         //检测已安装第三方应用数量
  103.         int userAppNumber = getUserAppNumber();
  104.         if (userAppNumber <= 5) ++suspectCount;
  105.         //检测是否支持闪光灯
  106.         boolean supportCameraFlash = supportCameraFlash(context);
  107.         if (!supportCameraFlash) ++suspectCount;
  108.         //检测是否支持相机
  109.         boolean supportCamera = supportCamera(context);
  110.         if (!supportCamera) ++suspectCount;
  111.         //检测是否支持蓝牙
  112.         boolean supportBluetooth = supportBluetooth(context);
  113.         if (!supportBluetooth) ++suspectCount;
  114.         //检测光线传感器
  115.         boolean hasLightSensor = hasLightSensor(context);
  116.         if (!hasLightSensor) ++suspectCount;
  117.         //检测进程组信息
  118.         CheckResult cgroupResult = checkFeaturesByCgroup();
  119.         if (cgroupResult.result == RESULT_MAYBE_EMULATOR) ++suspectCount;
  120.         if (callback != null) {
  121.             StringBuffer stringBuffer = new StringBuffer("Test start")
  122.                     .append("\r\n").append("hardware = ").append(hardwareResult.value)
  123.                     .append("\r\n").append("flavor = ").append(flavorResult.value)
  124.                     .append("\r\n").append("model = ").append(modelResult.value)
  125.                     .append("\r\n").append("manufacturer = ").append(manufacturerResult.value)
  126.                     .append("\r\n").append("board = ").append(boardResult.value)
  127.                     .append("\r\n").append("platform = ").append(platformResult.value)
  128.                     .append("\r\n").append("baseBand = ").append(baseBandResult.value)
  129.                     .append("\r\n").append("sensorNumber = ").append(sensorNumber)
  130.                     .append("\r\n").append("userAppNumber = ").append(userAppNumber)
  131.                     .append("\r\n").append("supportCamera = ").append(supportCamera)
  132.                     .append("\r\n").append("supportCameraFlash = ").append(supportCameraFlash)
  133.                     .append("\r\n").append("supportBluetooth = ").append(supportBluetooth)
  134.                     .append("\r\n").append("hasLightSensor = ").append(hasLightSensor)
  135.                     .append("\r\n").append("cgroupResult = ").append(cgroupResult.value)
  136.                     .append("\r\n").append("suspectCount = ").append(suspectCount);
  137.             callback.findEmulator(stringBuffer.toString());
  138.         }
  139.         //嫌疑值大于3,认为是模拟器
  140.         return suspectCount > 3;
  141.     }
  142.     private int getUserAppNum(String userApps) {
  143.         if (TextUtils.isEmpty(userApps)) return 0;
  144.         String[] result = userApps.split("package:");
  145.         return result.length;
  146.     }
  147.     private String getProperty(String propName) {
  148.         String property = CommandUtil.getSingleInstance().getProperty(propName);
  149.         return TextUtils.isEmpty(property) ? null : property;
  150.     }
  151.     /**
  152.      * 特征参数-硬件名称
  153.      *
  154.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  155.      */
  156.     private CheckResult checkFeaturesByHardware() {
  157.         String hardware = getProperty("ro.hardware");
  158.         if (null == hardware) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  159.         int result;
  160.         String tempValue = hardware.toLowerCase();
  161.         switch (tempValue) {
  162.             case "ttvm"://天天模拟器
  163.             case "nox"://夜神模拟器
  164.             case "cancro"://网易MUMU模拟器
  165.             case "intel"://逍遥模拟器
  166.             case "vbox":
  167.             case "vbox86"://腾讯手游助手
  168.             case "android_x86"://雷电模拟器
  169.                 result = RESULT_EMULATOR;
  170.                 break;
  171.             default:
  172.                 result = RESULT_UNKNOWN;
  173.                 break;
  174.         }
  175.         return new CheckResult(result, hardware);
  176.     }
  177.     /**
  178.      * 特征参数-渠道
  179.      *
  180.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  181.      */
  182.     private CheckResult checkFeaturesByFlavor() {
  183.         String flavor = getProperty("ro.build.flavor");
  184.         if (null == flavor) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  185.         int result;
  186.         String tempValue = flavor.toLowerCase();
  187.         if (tempValue.contains("vbox")) result = RESULT_EMULATOR;
  188.         else if (tempValue.contains("sdk_gphone")) result = RESULT_EMULATOR;
  189.         else result = RESULT_UNKNOWN;
  190.         return new CheckResult(result, flavor);
  191.     }
  192.     /**
  193.      * 特征参数-设备型号
  194.      *
  195.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  196.      */
  197.     private CheckResult checkFeaturesByModel() {
  198.         String model = getProperty("ro.product.model");
  199.         if (null == model) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  200.         int result;
  201.         String tempValue = model.toLowerCase();
  202.         if (tempValue.contains("google_sdk")) result = RESULT_EMULATOR;
  203.         else if (tempValue.contains("emulator")) result = RESULT_EMULATOR;
  204.         else if (tempValue.contains("android sdk built for x86")) result = RESULT_EMULATOR;
  205.         else result = RESULT_UNKNOWN;
  206.         return new CheckResult(result, model);
  207.     }
  208.     /**
  209.      * 特征参数-硬件制造商
  210.      *
  211.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  212.      */
  213.     private CheckResult checkFeaturesByManufacturer() {
  214.         String manufacturer = getProperty("ro.product.manufacturer");
  215.         if (null == manufacturer) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  216.         int result;
  217.         String tempValue = manufacturer.toLowerCase();
  218.         if (tempValue.contains("genymotion")) result = RESULT_EMULATOR;
  219.         else if (tempValue.contains("netease")) result = RESULT_EMULATOR;//网易MUMU模拟器
  220.         else result = RESULT_UNKNOWN;
  221.         return new CheckResult(result, manufacturer);
  222.     }
  223.     /**
  224.      * 特征参数-主板名称
  225.      *
  226.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  227.      */
  228.     private CheckResult checkFeaturesByBoard() {
  229.         String board = getProperty("ro.product.board");
  230.         if (null == board) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  231.         int result;
  232.         String tempValue = board.toLowerCase();
  233.         if (tempValue.contains("android")) result = RESULT_EMULATOR;
  234.         else if (tempValue.contains("goldfish")) result = RESULT_EMULATOR;
  235.         else result = RESULT_UNKNOWN;
  236.         return new CheckResult(result, board);
  237.     }
  238.     /**
  239.      * 特征参数-主板平台
  240.      *
  241.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  242.      */
  243.     private CheckResult checkFeaturesByPlatform() {
  244.         String platform = getProperty("ro.board.platform");
  245.         if (null == platform) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  246.         int result;
  247.         String tempValue = platform.toLowerCase();
  248.         if (tempValue.contains("android")) result = RESULT_EMULATOR;
  249.         else result = RESULT_UNKNOWN;
  250.         return new CheckResult(result, platform);
  251.     }
  252.     /**
  253.      * 特征参数-基带信息
  254.      *
  255.      * @return 0表示可能是模拟器,1表示模拟器,2表示可能是真机
  256.      */
  257.     private CheckResult checkFeaturesByBaseBand() {
  258.         String baseBandVersion = getProperty("gsm.version.baseband");
  259.         if (null == baseBandVersion) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  260.         int result;
  261.         if (baseBandVersion.contains("1.0.0.0")) result = RESULT_EMULATOR;
  262.         else result = RESULT_UNKNOWN;
  263.         return new CheckResult(result, baseBandVersion);
  264.     }
  265.     /**
  266.      * 获取传感器数量
  267.      */
  268.     private int getSensorNumber(Context context) {
  269.         SensorManager sm = (SensorManager) context.getSystemService(SENSOR_SERVICE);
  270.         return sm.getSensorList(Sensor.TYPE_ALL).size();
  271.     }
  272.     /**
  273.      * 获取已安装第三方应用数量
  274.      */
  275.     private int getUserAppNumber() {
  276.         String userApps = CommandUtil.getSingleInstance().exec("pm list package -3");
  277.         return getUserAppNum(userApps);
  278.     }
  279.     /**
  280.      * 是否支持相机
  281.      */
  282.     private boolean supportCamera(Context context) {
  283.         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
  284.     }
  285.     /**
  286.      * 是否支持闪光灯
  287.      */
  288.     private boolean supportCameraFlash(Context context) {
  289.         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
  290.     }
  291.     /**
  292.      * 是否支持蓝牙
  293.      */
  294.     private boolean supportBluetooth(Context context) {
  295.         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
  296.     }
  297.     /**
  298.      * 判断是否存在光传感器来判断是否为模拟器
  299.      * 部分真机也不存在温度和压力传感器。其余传感器模拟器也存在。
  300.      *
  301.      * @return false为模拟器
  302.      */
  303.     private boolean hasLightSensor(Context context) {
  304.         SensorManager sensorManager = (SensorManager) context.getSystemService(SENSOR_SERVICE);
  305.         Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光线传感器
  306.         if (null == sensor) return false;
  307.         else return true;
  308.     }
  309.     /**
  310.      * 特征参数-进程组信息
  311.      */
  312.     private CheckResult checkFeaturesByCgroup() {
  313.         String filter = CommandUtil.getSingleInstance().exec("cat /proc/self/cgroup");
  314.         if (null == filter) return new CheckResult(RESULT_MAYBE_EMULATOR, null);
  315.         return new CheckResult(RESULT_UNKNOWN, filter);
  316.     }
  317. }
复制代码
EmulatorCheckCallback (配置)

回调监听,可以获取到具体检测结果
  1. public interface EmulatorCheckCallback {
  2.     void findEmulator(String emulatorInfo);
  3. }
复制代码
CheckResult(配置)

对检测结果举行种别分别,方便管理
  1. public class CheckResult {
  2.     public static final int RESULT_MAYBE_EMULATOR = 0;//可能是模拟器
  3.     public static final int RESULT_EMULATOR = 1;//模拟器
  4.     public static final int RESULT_UNKNOWN = 2;//可能是真机
  5.     public int result;
  6.     public String value;
  7.     public CheckResult(int result, String value) {
  8.         this.result = result;
  9.         this.value = value;
  10.     }
  11. }
复制代码
调用方式

  1. val readSysProperty = EmulatorCheckUtil.getSingleInstance().readSysProperty(context, null)
  2. if (readSysProperty) {
  3.      //根据需要进行风险提示等相关业务
  4.      ToastUtils.showToast("您当前可能运行在模拟器设备,请谨防安全风险!")
  5. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4