赞
踩
最近游戏项目组又有新的要求,对于数据上报和数据统计接口,尽可能的具体化,比如是否是模拟器,模拟器的型号,品牌等,都要求统计,后续模拟器玩家在活动发放,安全风控等方面也易于分析和把控。
在网上搜了搜,大概思路是:
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
雷电
逍遥
夜神
官方AVD(用这个玩游戏基本没有)
http://dxtdbj.com/article.php?id=268
https://cloud.tencent.com/developer/article/2019963
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。