Repository: ysrc/Anti-Emulator Branch: master Commit: 05277af73983 Files: 37 Total size: 55.9 KB Directory structure: gitextract_q530vhma/ ├── .gitignore ├── .idea/ │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── README.md ├── app/ │ ├── .gitignore │ ├── CMakeLists.txt │ ├── app-release.apk │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── com/ │ │ └── qtfreet/ │ │ └── anticheckemulator/ │ │ └── ExampleInstrumentedTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── cpp/ │ │ │ └── native-lib.cpp │ │ ├── java/ │ │ │ └── com/ │ │ │ └── qtfreet/ │ │ │ └── anticheckemulator/ │ │ │ ├── MainActivity.java │ │ │ ├── emulator/ │ │ │ │ ├── Check.java │ │ │ │ ├── GLSurfaceView.java │ │ │ │ ├── GpuRender.java │ │ │ │ └── JniAnti.java │ │ │ └── utils/ │ │ │ └── Util.java │ │ └── res/ │ │ ├── layout/ │ │ │ └── activity_main.xml │ │ ├── values/ │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── values-w820dp/ │ │ └── dimens.xml │ └── test/ │ └── java/ │ └── com/ │ └── qtfreet/ │ └── anticheckemulator/ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures .externalNativeBuild ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/runConfigurations.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: README.md ================================================ # Anti-Emulator Android Anti Emulator 基于模拟器特征文件的检测方式,利用jni和java共同实现。 ####原理分析 [文章地址](http://mp.weixin.qq.com/s/sl33d2pnyLMJ-fUY_DfBDw) ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.4.1) add_library(native-lib SHARED src/main/cpp/native-lib.cpp ) find_library(log-lib log ) target_link_libraries(native-lib ${log-lib} ) ================================================ FILE: app/build.gradle ================================================ apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.0" defaultConfig { applicationId "com.qtfreet.anticheckemulator" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "-fexceptions" cppFlags "-O3" } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.0.1' testCompile 'junit:junit:4.12' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in D:\sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: app/src/androidTest/java/com/qtfreet/anticheckemulator/ExampleInstrumentedTest.java ================================================ package com.qtfreet.anticheckemulator; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; /** * Instrumentation test, which will execute on an Android device. * * @see Testing documentation */ @RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest { @Test public void useAppContext() throws Exception { // Context of the app under test. Context appContext = InstrumentationRegistry.getTargetContext(); assertEquals("com.qtfreet.anticheckemulator", appContext.getPackageName()); } } ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/cpp/native-lib.cpp ================================================ #include #include #include #include #include #include #include #include #include #include #include #include #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "qtfreet00", __VA_ARGS__) extern "C" { int i = 0; char *jstringToChar(JNIEnv *env, jstring jstr) { if (jstr == NULL) { return NULL; } char *rtn = new char; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char *) malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } else { rtn = ""; } /**资源清理**/ env->ReleaseByteArrayElements(barr, ba, 0); if (clsstring != NULL) { env->DeleteLocalRef(clsstring); clsstring = NULL; } if (strencode != NULL) { env->DeleteLocalRef(strencode); strencode = NULL; } mid = NULL; return rtn; } jstring chartoJstring(JNIEnv *env, const char *pat) { jclass strClass = env->FindClass("Ljava/lang/String;"); jmethodID ctorID = env->GetMethodID(strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat); jstring encoding = env->NewStringUTF("utf-8"); return (jstring) env->NewObject(strClass, ctorID, bytes, encoding); } jobject getApplication(JNIEnv *env) { jclass localClass = env->FindClass("android/app/ActivityThread"); if (localClass != NULL) { jmethodID getapplication = env->GetStaticMethodID(localClass, "currentApplication", "()Landroid/app/Application;"); if (getapplication != NULL) { jobject application = env->CallStaticObjectMethod(localClass, getapplication); return application; } return NULL; } return NULL; } char *verifySign(JNIEnv *env) { //此处用于获取app签名 jobject context = getApplication(env); jclass activity = env->GetObjectClass(context); // 得到 getPackageManager 方法的 ID jmethodID methodID_func = env->GetMethodID(activity, "getPackageManager", "()Landroid/content/pm/PackageManager;"); // 获得PackageManager对象 jobject packageManager = env->CallObjectMethod(context, methodID_func); jclass packageManagerclass = env->GetObjectClass(packageManager); //得到 getPackageName 方法的 ID jmethodID methodID_pack = env->GetMethodID(activity, "getPackageName", "()Ljava/lang/String;"); //获取包名 jstring name_str = static_cast(env->CallObjectMethod(context, methodID_pack)); // 得到 getPackageInfo 方法的 ID jmethodID methodID_pm = env->GetMethodID(packageManagerclass, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); // 获得应用包的信息 jobject package_info = env->CallObjectMethod(packageManager, methodID_pm, name_str, 64); // 获得 PackageInfo 类 jclass package_infoclass = env->GetObjectClass(package_info); // 获得签名数组属性的 ID jfieldID fieldID_signatures = env->GetFieldID(package_infoclass, "signatures", "[Landroid/content/pm/Signature;"); // 得到签名数组,待修改 jobject signatur = env->GetObjectField(package_info, fieldID_signatures); jobjectArray signatures = reinterpret_cast(signatur); // 得到签名 jobject signature = env->GetObjectArrayElement(signatures, 0); // 获得 Signature 类,待修改 jclass signature_clazz = env->GetObjectClass(signature); //获取sign jmethodID toCharString = env->GetMethodID(signature_clazz, "toCharsString", "()Ljava/lang/String;"); //获取签名字符;或者其他进行验证操作 jstring signstr = static_cast(env->CallObjectMethod(signature, toCharString)); char *ch = jstringToChar(env, signstr); //输入签名字符串,这里可以进行相关验证 return ch; } jstring getDeviceID(JNIEnv *env, jobject instance) { jobject mContext = getApplication(env); if (mContext == NULL) { return (env)->NewStringUTF("unknown"); } jclass cls_context = (env)->FindClass("android/content/Context"); if (cls_context == 0) { return (env)->NewStringUTF("unknown"); } jmethodID getSystemService = (env)->GetMethodID(cls_context, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); if (getSystemService == 0) { return (env)->NewStringUTF("unknown"); } jfieldID TELEPHONY_SERVICE = (env)->GetStaticFieldID(cls_context, "TELEPHONY_SERVICE", "Ljava/lang/String;"); if (TELEPHONY_SERVICE == 0) { return (env)->NewStringUTF("unknown"); } jobject str = (env)->GetStaticObjectField(cls_context, TELEPHONY_SERVICE); jobject telephonymanager = (env)->CallObjectMethod(mContext, getSystemService, str); if (telephonymanager == 0) { return (env)->NewStringUTF("unknown"); } jclass cls_tm = (env)->FindClass("android/telephony/TelephonyManager"); if (cls_tm == 0) { return (env)->NewStringUTF("unknown"); } jmethodID getDeviceId = (env)->GetMethodID(cls_tm, "getDeviceId", "()Ljava/lang/String;"); if (getDeviceId == 0) { return (env)->NewStringUTF("unknown"); } jstring deviceid = static_cast((env)->CallObjectMethod(telephonymanager, getDeviceId)); char *ch = jstringToChar(env, deviceid); return deviceid; } char *getCpuInfo() { //获取cpu型号 //此处在测试时去判断cpu型号是否是intel core,至强或者奔腾,AMD系列,x86手机cpu型号为intel atom,arm一般为联发科,高通,麒麟等等 //如是判断为前者,则认为当前环境为模拟器 char *info = new char[128]; memset(info, 0, 128); // char *res = new char[256]; // memset(res,0,256); char *split = ":"; char *cmd = "/proc/cpuinfo"; FILE *ptr; if ((ptr = fopen(cmd, "r")) != NULL) { while (fgets(info, 128, ptr)) { char *tmp = NULL; //去掉换行符 if (tmp = strstr(info, "\n")) *tmp = '\0'; //去掉回车符 if (tmp = strstr(info, "\r")) *tmp = '\0'; if (strstr(info, "Hardware")) { //真机一般会获取到hardware,示例:Qualcomm MSM 8974 HAMMERHEAD (Flattened Device Tree) strtok(info, split); char *s = strtok(NULL, split); return s; } else if (strstr(info, "model name")) { //测试了一个模拟器,取到的是model_name,示例:Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz strtok(info, split); char *s = strtok(NULL, split); //x86架构的移动处理器为Intel(R) Atom(TM) if (strstr(s, "Intel(R) Core(TM)") || strstr(s, "Intel(R) Pentium(R)") || strstr(s, "Intel(R) Xeon(R)") || strstr(s, "AMD")) { //分别为最常见的酷睿,奔腾,至强,AMD处理器 } LOGE("the cpu native info is %s", s); return s; } } } else { LOGE("NULLLLLLLLL"); } } char * getVersionInfo() { //获取设备版本,真机示例:Linux version 3.4.0-cyanogenmod (ls@ywk) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Apr 12 11:38:13 CST 2016 // 海马玩: Linux version 3.4.0-qemu+ (droid4x@CA) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #25 SMP PREEMPT Tue Sep 22 15:50:48 //腾讯模拟器中包含了tencent字眼 char *info = new char[256]; memset(info, 0, 256); char *cmd = "/proc/version"; FILE *ptr; if ((ptr = fopen(cmd, "r")) != NULL) { while (fgets(info, 256, ptr)) { char *tmp = NULL; if (tmp = strstr(info, "\n")) *tmp = '\0'; //去掉回车符 if (tmp = strstr(info, "\r")) *tmp = '\0'; //包含qemu+或者tencent均为模拟器 LOGE("the kernel info is %s", info); return info; } } else { LOGE("NULLLLLLLLL"); return NULL; } } void antiFile(char *res) { struct stat buf; int result = stat(res, &buf) == 0 ? 1 : 0; if (result) { LOGE("%s exsits, emulator!", res); // kill(getpid(),SIGKILL); i++; } } void antiProperty(char *res) { char buff[PROP_VALUE_MAX]; memset(buff, 0, PROP_VALUE_MAX); int result = __system_property_get(res, (char *) &buff) > 0 ? 1 : 0; //返回命令行内容的长度 if (result != 0) { LOGE("%s %s exsits, emulator!", res, buff); // kill(getpid(),SIGKILL); i++; } } void antiPropertyValueContains(char *res, char *val) { char buff[PROP_VALUE_MAX + 1]; memset(buff, 0, PROP_VALUE_MAX + 1); int lman = __system_property_get(res, buff); if (lman > 0) { if (strstr(buff, val) != NULL) { // match! LOGE("%s property value contains %s . Emulator!", res, val); i++; } } } void getDeviceInfo() { char buff[PROP_VALUE_MAX]; memset(buff, 0, PROP_VALUE_MAX); __system_property_get("ro.product.name", (char *) &buff); LOGE("the model name is %s", buff); if (!strcmp(buff, "ChangWan")) { // kill(getpid(),SIGKILL); } else if (!strcmp(buff, "Droid4X")) { //非0均为模拟器 // kill(getpid(),SIGKILL); } else if (!strcmp(buff, "lgshouyou")) { // kill(getpid(),SIGKILL); } else if (!strcmp(buff, "nox")) { // kill(getpid(),SIGKILL); } else if (!strcmp(buff, "ttVM_Hdragon")) { // kill(getpid(),SIGKILL); } } char *SocketTest(char *c) { struct sockaddr_in serv_addr; char buff[1024]; char res[4096]; memset(res, 0, 4096); memset(buff, 0, 1024); memset(&serv_addr, 0, sizeof(serv_addr)); char *addr = "107.151.180.166"; int socketfd = socket(AF_INET, SOCK_STREAM, 0); if (socketfd == -1) { LOGE("create error"); LOGE("error (errno=%d)", errno); exit(1); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(6666); serv_addr.sin_addr.s_addr = inet_addr(addr); if (serv_addr.sin_addr.s_addr == INADDR_NONE) { struct hostent *host = gethostbyname(addr); if (host == NULL) { LOGE("error (errno=%d)", errno); exit(1); } serv_addr.sin_addr.s_addr = ((struct in_addr *) host->h_addr)->s_addr; } memset(serv_addr.sin_zero, 0, sizeof(serv_addr.sin_zero)); int conn = connect(socketfd, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr)); if (conn == -1) { LOGE("connect error"); LOGE("error (errno=%d)", errno); exit(1); } int sen = send(socketfd, c, strlen(c), 0); if (sen == -1) { LOGE("send errorrr"); LOGE("error (errno=%d)", errno); exit(1); } while (recv(socketfd, buff, 1023, 0) > 0) { LOGE("%s", buff); strcpy(res, buff); } close(socketfd); LOGE("send successssss"); return res; } /*逍遥模拟器 * 12-13 12:20:58.671 1615-1615/? E/qtfreet00: the /system/bin/microvirt-prop is exist 12-13 12:20:58.671 1615-1615/? E/qtfreet00: the /system/bin/microvirtd is exist 12-13 12:20:58.671 1615-1615/? E/qtfreet00: the init.svc.vbox86-setup result is stopped 12-13 12:20:58.671 1615-1615/? E/qtfreet00: the init.svc.microvirtd result is running*/ jint check(JNIEnv *env, jobject instance) { antiFile("/system/bin/qemu_props"); //检测原生模拟器 // antiFile("/system/bin/qemud"); //小米会检测出此项 antiFile("/system/bin/androVM-prop"); antiFile("/system/bin/microvirt-prop");//逍遥 antiFile("/system/lib/libdroid4x.so"); //海马玩 antiFile("/system/bin/windroyed");//文卓爷 antiFile("/system/bin/microvirtd");//逍遥 antiFile("/system/bin/nox-prop"); //夜神 antiFile("/system/bin/ttVM-prop"); //天天 antiFile("/system/bin/droid4x-prop"); //海马玩 antiFile("/data/.bluestacks.prop");//bluestacks antiProperty("init.svc.vbox86-setup"); //基于vitrualbox antiProperty("init.svc.droid4x"); //海马玩 antiProperty("init.svc.qemud"); antiProperty("init.svc.su_kpbs_daemon"); antiProperty("init.svc.noxd"); //夜神 antiProperty("init.svc.ttVM_x86-setup"); //天天 antiProperty("init.svc.xxkmsg"); antiProperty("init.svc.microvirtd");//逍遥 // antiProperty("ro.secure"); //检测selinux是否被关闭,一般手机均开启此选项 antiProperty("ro.kernel.android.qemud"); // antiProperty("ro.kernel.qemu.gles"); //三星SM-G5500误报此项 antiProperty("androVM.vbox_dpi"); antiProperty("androVM.vbox_graph_mode"); antiPropertyValueContains("ro.product.manufacturer", "Genymotion"); // Genymotion check ,thx alinbaturn return i; } jstring getCpuinfo(JNIEnv *env, jobject instance) { char *res = getCpuInfo(); return env->NewStringUTF(res); } jstring getKernelVersion(JNIEnv *env, jobject /* this */) { char *res = getVersionInfo(); return env->NewStringUTF(res); } jstring getApkSign(JNIEnv *env, jobject /* this */) { char *res = verifySign(env); return env->NewStringUTF(res); } static const char *gClassName = "com/qtfreet/anticheckemulator/emulator/JniAnti"; static JNINativeMethod gMethods[] = { {"getApkSign", "()Ljava/lang/String;", (void *) getApkSign}, {"getKernelVersion", "()Ljava/lang/String;", (void *) getKernelVersion}, {"getCpuinfo", "()Ljava/lang/String;", (void *) getCpuinfo}, {"getDeviceID", "()Ljava/lang/String;", (void *) getDeviceID}, {"checkAntiFile", "()I", (void *) check}, }; static int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return JNI_FALSE; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return JNI_FALSE; } return JNI_TRUE; } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = NULL; jint result = -1; if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } //目前已知问题,检测/sys/class/thermal/和bluetooth-jni.so不稳定,存在兼容性问题 getDeviceInfo(); if (registerNativeMethods(env, gClassName, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) == JNI_FALSE) { return -1; } return JNI_VERSION_1_6; } } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/MainActivity.java ================================================ package com.qtfreet.anticheckemulator; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.widget.TextView; import com.qtfreet.anticheckemulator.emulator.Check; import com.qtfreet.anticheckemulator.emulator.JniAnti; import com.qtfreet.anticheckemulator.utils.Util; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = (TextView) findViewById(R.id.sample_text); GLSurfaceView gl = (GLSurfaceView) findViewById(R.id.hwGPU); gl.setRenderMode(0); //此处是为了加载显卡信息 Log.e("qtfreet000", "APK签名:" + JniAnti.getApkSign()); Log.e("qtfreet000", "程序包名:" + Check.getPackageName(this)); Log.e("qtfreet000", "CPU信息:" + JniAnti.getCpuinfo()); Log.e("qtfreet000", "CPU频率:" + Check.getCpuFrequency()); Log.e("qtfreet000", "CPU核心数量:" + Check.getCpuCore()); Log.e("qtfreet000", "内核信息:" + JniAnti.getKernelVersion()); Log.e("qtfreet000", "设备ID:" + JniAnti.getDeviceID()); Log.e("qtfreet000", "已安装App:" + Check.getInstalledApps(this)); Log.e("qtfreet000", "MAC地址:" + Check.getMacAddress(this)); Log.e("qtfreet000", "内存大小:" + Check.getMemorySize()); // Log.e("qtfreet000", "存在重力感应器:" + Check.checkGravity(this)); //这点不靠谱,很多手机还是检测不出来 Log.e("qtfreet000", "设备厂商:" + Check.getModelBrand()); Log.e("qtfreet000", "设备型号:" + Check.getModelName()); Log.e("qtfreet000", "支持GPS:" + Check.hasGPSDevice(this)); Log.e("qtfreet000", "支持多点触控:" + Check.checkMultiTouch(this)); Log.e("qtfreet000", "电池温度:" + Check.getBatteryTemp(this)); Log.e("qtfreet000", "电池电压:" + Check.getBatteryVolt(this)); Log.e("qtfreet000", "模拟器特征数量:" + JniAnti.checkAntiFile()); String cpu = JniAnti.getCpuinfo(); String cpuFreq = Util.convertSize(Check.getCpuMaxFrequency()); String kernel = JniAnti.getKernelVersion(); boolean gravity = Check.checkGravity(this); String temp = Check.getBatteryTemp(this); String volt = Check.getBatteryVolt(this); int check = JniAnti.checkAntiFile(); boolean gps = Check.hasGPSDevice(this); StringBuilder sb = new StringBuilder(); if (cpu.contains("Genuine Intel(R)") || cpu.contains("Intel(R) Core(TM)") || cpu.contains("Intel(R) Pentium(R)") || cpu.contains("Intel(R) Xeon(R)") || cpu.contains("AMD")) { sb.append("特征一:" + cpu + "\n"); } if (kernel.contains("qemu+") || kernel.contains("tencent") || kernel.contains("virtualbox")) { sb.append("特征二:" + kernel + "\n"); } if (gravity == false) { sb.append("特征三:" + "无重力感应器\n"); } if (TextUtils.isEmpty(temp)) { sb.append("特征四:" + "无电池温度\n"); } if (TextUtils.isEmpty(volt)) { sb.append("特征五:" + "无电池电压\n"); } if (check > 0) { sb.append("特征六:" + "模拟器特征文件\n"); } if (gps == false) { sb.append("特征七:" + "无gps\n"); } if (cpuFreq.equals("0M")) { sb.append("特征八:" + "cpu无频率\n"); } tv.setText(sb.toString()); } } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/emulator/Check.java ================================================ package com.qtfreet.anticheckemulator.emulator; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.hardware.Sensor; import android.hardware.SensorManager; import android.location.LocationManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.telephony.TelephonyManager; import com.qtfreet.anticheckemulator.utils.Util; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import static android.content.Context.SENSOR_SERVICE; import static android.hardware.Sensor.TYPE_GRAVITY; import static com.qtfreet.anticheckemulator.utils.Util.tempToStr; /** * Created by qtfreet on 2016/12/22. */ public class Check { private final static String CPUFREQ_CPUINFO_MAX_FREQ = "/cpufreq/cpuinfo_max_freq"; private final static String CPUFREQ_CPUINFO_MIN_FREQ = "/cpufreq/cpuinfo_min_freq"; private final static String CPUFREQ_SCALING_CUR_FREQ = "/cpufreq/scaling_cur_freq"; public static boolean checkGravity(Context context) { boolean z = false; List defaultSensor = ((SensorManager) context.getSystemService(SENSOR_SERVICE)).getSensorList(Sensor.TYPE_ALL); for (Sensor sensor : defaultSensor) { if (sensor.getType() == TYPE_GRAVITY) { //不能使用getName去判断是否存在重力感应器,应交与系统判断 z = true; break; } } return z; } public static List getAllSensors(Context context) { List list = new ArrayList<>(); List defaultSensor = ((SensorManager) context.getSystemService(SENSOR_SERVICE)).getSensorList(Sensor.TYPE_ALL); for (Sensor sensor : defaultSensor) { list.add(sensor.getName()); } return list; } public static int getVersionCode(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); if (packageInfo != null) { return packageInfo.versionCode; } return 0; } catch (Throwable th) { return 0; } } public static String getVersionName(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); if (packageInfo != null) { return packageInfo.versionName; } return null; } catch (Throwable th) { return null; } } public static String getInstalledApps(Context context) { List installedPackages = context.getPackageManager().getInstalledPackages(0); HashMap map = new HashMap<>(); for (PackageInfo p : installedPackages) { String packageName = p.packageName; String versionName = p.versionName; map.put(packageName, versionName); } return Util.hashMapToStringNoSort(map); } public static String getPackageName(Context context) { return context.getPackageName(); } public static boolean checkMultiTouch(Context context) { boolean z = false; try { z = context.getPackageManager().hasSystemFeature("android.hardware.touchscreen.multitouch"); } catch (Exception e) { e.printStackTrace(); } return z; } public static String getModelName() { return Build.MODEL; //Mumu为网易模拟器 } public static String getModelBrand() { return Build.BRAND; } public static String getMacAddress(Context context) { String str = ""; try { WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); if (wifiManager != null) { WifiInfo connectionInfo = wifiManager.getConnectionInfo(); return connectionInfo == null ? "" : connectionInfo.getMacAddress(); } } catch (Throwable th) { } return str; } public static String getDeviceID(Context context) { String str = null; TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager == null) { return str; } str = telephonyManager.getDeviceId(); return str; } public static String getMemorySize() { String dir = "/proc/meminfo"; FileReader fr = null; int size = 0; try { fr = new FileReader(dir); BufferedReader br = new BufferedReader(fr, 2048); String memoryLine = br.readLine(); String subMemoryLine = memoryLine.substring(memoryLine.indexOf("MemTotal:")); br.close(); long j = Long.parseLong(subMemoryLine.substring(subMemoryLine.indexOf(58) + 1, subMemoryLine.indexOf("kB")).trim()); size = (int) (j / 1024); } catch (FileNotFoundException e) { // e.printStackTrace(); } catch (IOException e) { // e.printStackTrace(); } if (size < 768) { return size + "M"; } if (size < 1024) { return "1G"; } return String.format("%.1fG", new Object[]{Float.valueOf(((float) size) / 1024.0f)}); } public static int getCpuCore() { try { return new File("/sys/devices/system/cpu/").listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return Pattern.matches("cpu[0-9]", pathname.getName()); } }).length; } catch (Exception e) { return 0; } } public static boolean hasGPSDevice(Context context) { final LocationManager mgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); if (mgr == null) return false; final List providers = mgr.getAllProviders(); if (providers == null) return false; return providers.contains(LocationManager.GPS_PROVIDER); } public static String getCpuFrequency() { String frequency = Util.convertSize(getCpuMaxFrequency()); String model = Build.MODEL; if (Build.BRAND.equalsIgnoreCase("samsung") && (model.equalsIgnoreCase("sch-i959") || model.equalsIgnoreCase("gt-i9500"))) { frequency = frequency + " " + "四核+四核"; return frequency; } switch (getCpuCore()) { case 1: frequency = frequency + " " + "单核"; break; case 2: frequency = frequency + " " + "双核"; break; case 4: frequency = frequency + " " + "四核"; break; case 6: frequency = frequency + " " + "六核"; break; case 8: frequency = frequency + " " + "八核"; break; } return frequency.trim(); } public static int getCpuMaxFrequency() { File file = new File("/sys/devices/system/cpu"); if (!file.exists()) { return 0; } File[] listFiles = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return Pattern.matches("cpu[0-9]", pathname.getName()); } }); if (listFiles == null || listFiles.length <= 0) { return 0; } List arrayList = new ArrayList(); for (File absolutePath : listFiles) { String path = absolutePath.getAbsolutePath(); try { int max = Math.max(Math.max(Integer.parseInt(Util.readFile(path + CPUFREQ_CPUINFO_MAX_FREQ)), Integer.parseInt(Util.readFile(path + CPUFREQ_SCALING_CUR_FREQ))), Integer.parseInt(Util.readFile(path + CPUFREQ_CPUINFO_MIN_FREQ))); if (max > 0) { arrayList.add(Integer.valueOf(max)); } } catch (Throwable th) { } } if (arrayList.isEmpty()) { return 0; } Collections.sort(arrayList); return ((Integer) arrayList.get(arrayList.size() - 1)).intValue(); } // // public static String getCameraPixels(Context context, int size) { // if (size == -1) { // return null; // } // Camera camera = Camera.open(size); // Camera.Parameters parameters = camera.getParameters(); // List localList = parameters.getSupportedPictureSizes(); // if (localList != null) { // int[] heights = new int[localList.size()]; // int[] widths = new int[localList.size()]; // for (int i = 0; i < localList.size(); i++) { // Camera.Size s = localList.get(i); // int sizehieght = s.height; // int sizewidth = s.width; // heights[i] = sizehieght; // widths[i] = sizewidth; // } // int pixels = getMaxNumber(heights) * getMaxNumber(widths); // camera.release(); // return String.valueOf(pixels / 10000) + " 万"; // } // return null; // // } // // private static int getMaxNumber(int[] paramArray) { // int temp = paramArray[0]; // for (int i = 0; i < paramArray.length; i++) { // if (temp < paramArray[i]) { // temp = paramArray[i]; // } // } // return temp; // } // // public static int HasBackCamera() { // int numberOfCameras = Camera.getNumberOfCameras(); // Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); // for (int i = 0; i < numberOfCameras; i++) { // Camera.getCameraInfo(i, cameraInfo); // if (cameraInfo.facing == 0) { // return i; // } // } // return -1; // } // // public static int HasFrontCamera() { // int numberOfCameras = Camera.getNumberOfCameras(); // Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); // for (int i = 0; i < numberOfCameras; i++) { // Camera.getCameraInfo(i, cameraInfo); // if (cameraInfo.facing == 1) { // return i; // } // } // return -1; // } public static String getBatteryTemp(Context act) { if (act == null) { return null; } Intent batteryStatus = act.registerReceiver(null, new IntentFilter("android.intent.action.BATTERY_CHANGED")); if (batteryStatus == null) { return null; } int temp = batteryStatus.getIntExtra("temperature", -1); if (temp > 0) { return tempToStr(((float) temp) / 10.0f, 1); } return null; } public static String getBatteryVolt(Context act) { if (act == null) { return null; } Intent batteryStatus = act.registerReceiver(null, new IntentFilter("android.intent.action.BATTERY_CHANGED")); if (batteryStatus == null) { return null; } int volt = batteryStatus.getIntExtra("voltage", -1); if (volt > 0) { return String.valueOf(volt); } return null; } public static String toInfoString(Context context) { HashMap map = new HashMap<>(); map.put("cpuinfo", JniAnti.getCpuinfo()); map.put("kernelVersion", JniAnti.getKernelVersion()); map.put("deviceId", JniAnti.getDeviceID()); // map.put("ApkSign", JniAnti.getApkSign()); map.put("cpuCore", String.valueOf(getCpuCore())); map.put("cpuFreq", getCpuFrequency()); map.put("Gravity", String.valueOf(checkGravity(context))); map.put("BatteryVolt", getBatteryVolt(context)); map.put("BatteryTemp", getBatteryTemp(context)); map.put("gps", String.valueOf(hasGPSDevice(context))); //map.put("installedApps",getInstalledApps(context)); map.put("ModelBrand", getModelBrand()); map.put("ModelName", getModelName()); map.put("MacAddress", getMacAddress(context)); String s = Util.hashMapToStringSort(map); return s; } } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/emulator/GLSurfaceView.java ================================================ package com.qtfreet.anticheckemulator.emulator; import android.content.Context; import android.util.AttributeSet; /** * Created by qtfreet on 2016/12/23. */ public class GLSurfaceView extends android.opengl.GLSurfaceView { public GLSurfaceView(Context context) { super(context); init(); } public GLSurfaceView(Context context, AttributeSet attributeSet) { super(context, attributeSet); init(); } private void init() { setEGLConfigChooser(8, 8, 8, 8, 16, 0); GpuRender gpuRender = new GpuRender(); setRenderer(gpuRender); } } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/emulator/GpuRender.java ================================================ package com.qtfreet.anticheckemulator.emulator; import android.opengl.GLSurfaceView; import android.util.Log; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; /** * Created by qtfreet on 2016/12/23. */ public class GpuRender implements GLSurfaceView.Renderer { @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(8.0f, 8.0f, 8.0f, 0.0f); String vendor = gl.glGetString(GL10.GL_VENDOR); String renderer = gl.glGetString(GL10.GL_RENDERER); Log.e("qtfreet000", "显卡信息:" + vendor + " " + renderer); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { } @Override public void onDrawFrame(GL10 gl) { } } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/emulator/JniAnti.java ================================================ package com.qtfreet.anticheckemulator.emulator; /** * Created by qtfreet on 2016/12/22. */ public class JniAnti { static { System.loadLibrary("native-lib"); } public static native String getCpuinfo(); public static native String getApkSign(); public static native String getKernelVersion(); public static native String getDeviceID(); //优测测试时提示没有权限读取read_phone_state,这里已经Mainifest注册 public static native int checkAntiFile(); } ================================================ FILE: app/src/main/java/com/qtfreet/anticheckemulator/utils/Util.java ================================================ package com.qtfreet.anticheckemulator.utils; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Set; /** * Created by qtfreet on 2017/2/7. */ public class Util { public static String hashMapToStringNoSort(HashMap paramMap) { Set listKeys = paramMap.keySet(); int length = listKeys.size(); List list = new ArrayList(); for (String add : listKeys) { list.add(add); } String kvString = ""; for (int i = 0; i < length; i++) { String key = list.get(i); if (i == length - 1) { kvString = kvString + key + "=" + paramMap.get(key); } else { kvString = kvString + key + "=" + paramMap.get(key) + "&"; } } return kvString; } public static String hashMapToStringSort(HashMap paramMap) { Set listKeys = paramMap.keySet(); int length = listKeys.size(); List list = new ArrayList(); for (String add : listKeys) { list.add(add); } Collections.sort(list); //进行排序 String kvString = ""; for (int i = 0; i < length; i++) { String key = list.get(i); if (i == length - 1) { kvString = kvString + key + "=" + paramMap.get(key); } else { kvString = kvString + key + "=" + (paramMap.get(key)) + "&"; } } return kvString; } public static String readFile(String str) { File file = new File(str); StringBuilder sb = new StringBuilder(); if (file.exists()) { try { String line = null; FileInputStream fileInputStream = new FileInputStream(file); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream)); while ((line = bufferedReader.readLine()) != null) { sb.append(line); } bufferedReader.close(); fileInputStream.close(); return sb.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } return ""; } public static String convertSize(int i) { int size = i / 1000; if (size > 360 && size < 440) { return "400M"; } if (size > 460 && size < 540) { return "500M"; } if (size > 560 && size < 640) { return "600M"; } if (size > 660 && size < 740) { return "700M"; } if (size > 760 && size < 840) { return "800M"; } if (size > 860 && size < 940) { return "900M"; } if (size > 960 && size < 1040) { return "1G"; } if (size < 1000) { return String.format("%dM", new Object[]{Integer.valueOf(size)}); } return String.format("%.1fG", new Object[]{Float.valueOf(((float) size) / 1000.0f)}); } public static String tempToStr(float temp, int tempSetting) { if (temp <= 0.0f) { return ""; } if (tempSetting == 2) { return String.format("%.1f°F", new Object[]{Float.valueOf(((9.0f * temp) + 160.0f) / 5.0f)}); } return String.format("%.1f°C", new Object[]{Float.valueOf(temp)}); } } ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================ ================================================ FILE: app/src/main/res/values/colors.xml ================================================ #3F51B5 #303F9F #FF4081 ================================================ FILE: app/src/main/res/values/dimens.xml ================================================ 16dp 16dp ================================================ FILE: app/src/main/res/values/strings.xml ================================================ AntiCheckEmulator ================================================ FILE: app/src/main/res/values/styles.xml ================================================ ================================================ FILE: app/src/main/res/values-w820dp/dimens.xml ================================================ 64dp ================================================ FILE: app/src/test/java/com/qtfreet/anticheckemulator/ExampleUnitTest.java ================================================ package com.qtfreet.anticheckemulator; import org.junit.Test; import static org.junit.Assert.*; /** * Example local unit test, which will execute on the development machine (host). * * @see Testing documentation */ public class ExampleUnitTest { @Test public void addition_isCorrect() throws Exception { assertEquals(4, 2 + 2); } } ================================================ FILE: build.gradle ================================================ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.0-beta3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ #Tue Dec 27 10:06:56 CST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip ================================================ FILE: gradle.properties ================================================ ## Project-wide Gradle settings. # # For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html # # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx1024m -XX:MaxPermSize=256m # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Mon Dec 12 16:39:56 CST 2016 systemProp.http.proxyHost=127.0.0.1 org.gradle.jvmargs=-Xmx1536m systemProp.http.proxyPort=1080 ================================================ FILE: gradlew ================================================ #!/usr/bin/env bash ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn ( ) { echo "$*" } die ( ) { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; esac # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules function splitJvmOpts() { JVM_OPTS=("$@") } eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" ================================================ FILE: gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windowz variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* goto execute :4NT_args @rem Get arguments from the 4NT Shell from JP Software set CMD_LINE_ARGS=%$ :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: settings.gradle ================================================ include ':app'