当前位置:   article > 正文

android识别模拟器_emulator-check

emulator-check

 

识别安卓模拟器的两种方案!

禁止通过模拟器进行刷量,防止作弊行为!

  1. import android.content.Context;
  2. import android.content.Intent;
  3. import android.net.Uri;
  4. import android.os.Build;
  5. import android.telephony.TelephonyManager;
  6. import java.io.BufferedInputStream;
  7. import java.io.BufferedOutputStream;
  8. import java.io.IOException;
  9. public class EmulatorCheckUtil {
  10. /**
  11. * 方案一:通过检测设备信息来判断设备是否为模拟器
  12. *
  13. * @param context
  14. * @return
  15. */
  16. public static boolean isEmulator(Context context) {
  17. if (context == null) {
  18. return false;
  19. }
  20. String url = "tel:" + "123456";
  21. Intent intent = new Intent();
  22. intent.setData(Uri.parse(url));
  23. intent.setAction(Intent.ACTION_DIAL);
  24. // 是否可以处理跳转到拨号的 Intent
  25. boolean canResolverIntent = intent.resolveActivity(context.getPackageManager()) != null;
  26. return Build.FINGERPRINT.startsWith("generic")
  27. || Build.FINGERPRINT.toLowerCase().contains("vbox")
  28. || Build.FINGERPRINT.toLowerCase().contains("test-keys")
  29. || Build.MODEL.contains("google_sdk")
  30. || Build.MODEL.contains("Emulator")
  31. || Build.SERIAL.equalsIgnoreCase("unknown")
  32. || Build.SERIAL.equalsIgnoreCase("android")
  33. || Build.MODEL.contains("Android SDK built for x86")
  34. || Build.MANUFACTURER.contains("Genymotion")
  35. || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
  36. || "google_sdk".equals(Build.PRODUCT)
  37. || ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getNetworkOperatorName().toLowerCase().equals("android")
  38. || !canResolverIntent;
  39. }
  40. /**
  41. * 方案二:通过一系列的研究,得出一个嫌疑指数,综合判断是否运行在模拟器中
  42. * 在AS模拟器上判断失准,可以与方案一相结合使用
  43. *
  44. * @return
  45. */
  46. public static boolean checkIsRunningInEmulator() {
  47. int suspectCount = 0;
  48. // 读基带信息
  49. String baseBandVersion = getProperty("gsm.version.baseband");
  50. if (baseBandVersion == null | "".equals(baseBandVersion)) {
  51. ++suspectCount;
  52. }
  53. // 读渠道信息,针对一些基于vBox的模拟器
  54. String buildFlavor = getProperty("ro.build.flavor");
  55. if (buildFlavor == null | "".equals(buildFlavor) | (buildFlavor != null && buildFlavor.contains("vbox"))) {
  56. ++suspectCount;
  57. }
  58. // 读处理器信息,这里经常会被处理
  59. String productBoard = getProperty("ro.product.board");
  60. if (productBoard == null | "".equals(productBoard)) {
  61. ++suspectCount;
  62. }
  63. // 读处理器平台,这里不常会处理
  64. String boardPlatform = getProperty("ro.board.platform");
  65. if (boardPlatform == null | "".equals(boardPlatform)) {
  66. ++suspectCount;
  67. }
  68. // 高通的cpu两者信息一般是一致的
  69. if (productBoard != null && boardPlatform != null && !productBoard.equals(boardPlatform)) {
  70. ++suspectCount;
  71. }
  72. // 一些模拟器读取不到进程租信息
  73. String filter = exec("cat /proc/self/cgroup");
  74. if (filter == null || filter.length() == 0) {
  75. ++suspectCount;
  76. }
  77. return suspectCount > 2;
  78. }
  79. private static String getProperty(String propName) {
  80. String value = null;
  81. Object roSecureObj;
  82. try {
  83. roSecureObj = Class.forName("android.os.SystemProperties")
  84. .getMethod("get", String.class)
  85. .invoke(null, propName);
  86. if (roSecureObj != null) {
  87. value = (String) roSecureObj;
  88. }
  89. } catch (Exception e) {
  90. value = null;
  91. } finally {
  92. return value;
  93. }
  94. }
  95. private static String exec(String command) {
  96. BufferedOutputStream bufferedOutputStream = null;
  97. BufferedInputStream bufferedInputStream = null;
  98. Process process = null;
  99. try {
  100. process = Runtime.getRuntime().exec("sh");
  101. bufferedOutputStream = new BufferedOutputStream(process.getOutputStream());
  102. bufferedInputStream = new BufferedInputStream(process.getInputStream());
  103. bufferedOutputStream.write(command.getBytes());
  104. bufferedOutputStream.write('\n');
  105. bufferedOutputStream.flush();
  106. bufferedOutputStream.close();
  107. process.waitFor();
  108. String outputStr = getStrFromBufferInputSteam(bufferedInputStream);
  109. return outputStr;
  110. } catch (Exception e) {
  111. return null;
  112. } finally {
  113. if (bufferedOutputStream != null) {
  114. try {
  115. bufferedOutputStream.close();
  116. } catch (IOException e) {
  117. e.printStackTrace();
  118. }
  119. }
  120. if (bufferedInputStream != null) {
  121. try {
  122. bufferedInputStream.close();
  123. } catch (IOException e) {
  124. e.printStackTrace();
  125. }
  126. }
  127. if (process != null) {
  128. process.destroy();
  129. }
  130. }
  131. }
  132. private static String getStrFromBufferInputSteam(BufferedInputStream bufferedInputStream) {
  133. if (null == bufferedInputStream) {
  134. return "";
  135. }
  136. int BUFFER_SIZE = 512;
  137. byte[] buffer = new byte[BUFFER_SIZE];
  138. StringBuilder result = new StringBuilder();
  139. try {
  140. while (true) {
  141. int read = bufferedInputStream.read(buffer);
  142. if (read > 0) {
  143. result.append(new String(buffer, 0, read));
  144. }
  145. if (read < BUFFER_SIZE) {
  146. break;
  147. }
  148. }
  149. } catch (Exception e) {
  150. e.printStackTrace();
  151. }
  152. return result.toString();
  153. }
  154. }

 

如果担心会误判,把真正的用户档在门外,可以做一个接口收集设备信息,通过设备信息进行审核,如果确实不是模拟器,然后再放行。

  1. if (EmulatorCheckUtil.isEmulator(this)) {
  2. // 请求接口,收集并发送设备信息至服务端,并且通过接口返回数据,决定是否绿色放行
  3. // 弹窗对话框,询问用户是否需要反馈模拟器误判
  4. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/261848
推荐阅读
相关标签
  

闽ICP备14008679号