├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── gradle.xml └── misc.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── jni │ ├── AOBScan.h │ ├── Android.mk │ ├── Application.mk │ ├── Memory.h │ └── jni_draw.cpp ├── libs │ ├── armeabi-v7a │ │ └── libjni_draw.so │ └── x86 │ │ └── libjni_draw.so ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── shocker │ │ └── jnidraw │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── native-lib.cpp │ ├── java │ │ └── com │ │ │ └── shocker │ │ │ └── jnidraw │ │ │ ├── MainActivity.java │ │ │ └── OverlayView.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── shocker │ └── jnidraw │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img └── image.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Shocker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android_float_view_draw 2 | 3 | 植物大战僵尸网盘地址: 4 | 5 | 链接:https://pan.baidu.com/s/15N_GaoDQBGPfIfXwfvA9dA 6 | 7 | 提取码:zd68 8 | 9 | ## root进程 10 | root进程代码在 ./app/jni 11 | 该进程负责读取游戏内僵尸的坐标并使用udp转发. 12 | ### root进程编译 13 | 在./app/jni目录下执行ndk-build 14 | 生成的可执行文件在 15 | ``` 16 | ./app/libs 17 | ``` 18 | 将jni_draw改名为 19 | ``` 20 | libjni_draw.so 21 | ``` 22 | 配置build.gradle 23 | 在android里加上 24 | ``` 25 | sourceSets { 26 | main { 27 | jniLibs.srcDirs = ['libs'] 28 | } 29 | } 30 | ``` 31 | 就把可执行文件打包到app中 32 | ## app 33 | 用最新版android studio打开,直接点右上方运行即可 34 | 35 | ![image](img/image.jpg) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdk 30 7 | 8 | defaultConfig { 9 | applicationId "com.shocker.jnidraw" 10 | minSdk 21 11 | targetSdk 30 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | externalNativeBuild { 17 | cmake { 18 | cppFlags '' 19 | } 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | externalNativeBuild { 34 | cmake { 35 | path file('src/main/cpp/CMakeLists.txt') 36 | version '3.10.2' 37 | } 38 | } 39 | buildFeatures { 40 | viewBinding true 41 | } 42 | sourceSets { 43 | main { 44 | jniLibs.srcDirs = ['libs'] 45 | } 46 | } 47 | } 48 | 49 | dependencies { 50 | 51 | implementation 'androidx.appcompat:appcompat:1.2.0' 52 | implementation 'com.google.android.material:material:1.3.0' 53 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 54 | testImplementation 'junit:junit:4.+' 55 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 56 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 57 | } -------------------------------------------------------------------------------- /app/jni/AOBScan.h: -------------------------------------------------------------------------------- 1 | #ifndef AOBSCAN_H 2 | #define AOBSCAN_H 3 | 4 | 5 | //两内存地址逐一比较 6 | bool Memcmp(unsigned const char *target,unsigned const char *pattern, int Len) 7 | { 8 | for (int i = 0; i < Len; i++) 9 | { 10 | if (target[i] == pattern[i]) 11 | { 12 | continue; 13 | } 14 | else 15 | { 16 | return false; 17 | } 18 | } 19 | return true; 20 | } 21 | 22 | //特征码搜索 23 | int AOBScan(unsigned const char *target, int tLen, unsigned const char *pattern, int pLen) 24 | { 25 | if (tLen 5 | #include 6 | #include 7 | 8 | #define MEM_MAPPED 262144 9 | #define MEM_PRIVATE 131072 10 | 11 | using namespace std; 12 | 13 | typedef struct 14 | { 15 | unsigned long long baseAddress; 16 | void *next_ptr; 17 | int moduleSize; 18 | char *moduleName; 19 | 20 | } ModuleListEntry, *PModuleListEntry; 21 | 22 | //获取进程pid 23 | pid_t find_pid(const char *process_name) 24 | { 25 | int id; 26 | pid_t pid = -1; 27 | DIR *dir; 28 | FILE *fp; 29 | char filename[32]; 30 | char cmdline[256]; 31 | 32 | struct dirent *entry; 33 | if (process_name == NULL) 34 | { 35 | return -1; 36 | } 37 | dir = opendir("/proc"); 38 | if (dir == NULL) 39 | { 40 | return -1; 41 | } 42 | while ((entry = readdir(dir)) != NULL) 43 | { 44 | id = atoi(entry->d_name); 45 | if (id != 0) 46 | { 47 | sprintf(filename, "/proc/%d/cmdline", id); 48 | fp = fopen(filename, "r"); 49 | if (fp) 50 | { 51 | fgets(cmdline, sizeof(cmdline), fp); 52 | fclose(fp); 53 | 54 | if (strcmp(process_name, cmdline) == 0) 55 | { 56 | /* process found */ 57 | pid = id; 58 | break; 59 | } 60 | } 61 | } 62 | } 63 | 64 | closedir(dir); 65 | return pid; 66 | } 67 | 68 | //获取mmap内存,在Android5.1可以当作共享内存通信 69 | char *get_mmap_memory(const char *file, int size) 70 | { 71 | int MAP_SIZE = size; 72 | //打开文件,fd文件句柄 73 | int fd = open(file, O_RDWR | O_CREAT, 0644); 74 | 75 | if (fd < 0) 76 | { 77 | printf("Can't open %s\n", file); 78 | return nullptr; 79 | } 80 | ftruncate(fd, MAP_SIZE); 81 | 82 | char *mapped = (char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 83 | 84 | if (mapped == MAP_FAILED) 85 | { 86 | printf("File mmap failed\n"); 87 | return nullptr; 88 | } 89 | 90 | //映射结束,关闭文件 91 | close(fd); 92 | 93 | return mapped; 94 | } 95 | 96 | //取消mmap内存映射 97 | void close_mmap_memory(char *mapped, int size) 98 | { 99 | munmap(mapped, size); 100 | } 101 | 102 | //根据pid获取模块基址 103 | unsigned int get_module_base(int target_pid, const char *module_name) 104 | { 105 | FILE *fp; 106 | unsigned int addr = 0; 107 | char filename[32], buffer[1024]; 108 | snprintf(filename, sizeof(filename), "/proc/%d/maps", target_pid); 109 | fp = fopen(filename, "rt"); 110 | if (fp != nullptr) 111 | { 112 | while (fgets(buffer, sizeof(buffer), fp)) 113 | { 114 | if (strstr(buffer, module_name)) 115 | { 116 | addr = (uintptr_t)strtoul(buffer, nullptr, 16); 117 | break; 118 | } 119 | } 120 | fclose(fp); 121 | } 122 | return addr; 123 | } 124 | 125 | //mem方式读取内存 126 | //pid 目标进程pid 127 | //lpAddress 目标进程内存地址 128 | //buffer 读入数据的缓冲区 129 | //size 读入数据大小 130 | int ReadProcessMemory(int pid, void *lpAddress, void *buffer, int size) 131 | { 132 | char processpath[100]; 133 | sprintf(processpath, "/proc/%d/mem", pid); 134 | int fd = open(processpath, O_RDONLY); 135 | lseek64(fd, (uintptr_t)lpAddress, SEEK_SET); 136 | 137 | int bread = read(fd, buffer, size); 138 | 139 | if (bread == -1) 140 | { 141 | // printf("ReadProcessMemory fail\n"); 142 | bread = 0; 143 | } 144 | close(fd); 145 | return bread; 146 | } 147 | 148 | /* Write NLONG 4 byte words from BUF into PID starting 149 | at address POS. Calling process must be attached to PID. */ 150 | //参数和上面读内存一样 151 | int WriteProcessMemory(int pid, void *lpAddress, void *buffer, int size) 152 | { 153 | int result = ptrace(PTRACE_ATTACH, pid, NULL, NULL); 154 | if (result != 0) 155 | { 156 | printf("ptrace error(%d)!\n", result); 157 | return -1; 158 | } 159 | int status; 160 | pid = wait(&status); 161 | 162 | unsigned long *p; 163 | int i; 164 | 165 | for (p = (unsigned long *)buffer, i = 0; i < size; p++, i++) 166 | { 167 | if (0 > ptrace(PTRACE_POKETEXT, pid, (void *)((unsigned long)lpAddress + (i * 4)), (void *)*p)) 168 | { 169 | result = -1; 170 | break; 171 | } 172 | } 173 | result = ptrace(PTRACE_DETACH, pid, 0, 0); 174 | return result; 175 | } 176 | 177 | //获取进程所有模块信息 178 | //这里部分来源ce-server 179 | PModuleListEntry get_process_map(int pid) 180 | { 181 | int max = 64; 182 | char mapfile[255]; 183 | FILE *f = NULL; 184 | snprintf(mapfile, 255, "/proc/%d/maps", pid); 185 | 186 | f = fopen(mapfile, "r"); 187 | 188 | if (f) 189 | { 190 | char s[512]; 191 | memset(s, 0, 512); 192 | PModuleListEntry _ml = nullptr; 193 | PModuleListEntry ret = nullptr; 194 | while (fgets(s, 511, f)) //read a line into s 195 | { 196 | char *currentModule; 197 | unsigned long long start, stop; 198 | char memoryrange[64], protectionstring[32], modulepath[511]; 199 | uint32_t magic; 200 | 201 | modulepath[0] = '\0'; 202 | memset(modulepath, 0, 511); 203 | 204 | sscanf(s, "%llx-%llx %s %*s %*s %*s %[^\t\n]\n", &start, &stop, protectionstring, modulepath); 205 | 206 | if (strchr(protectionstring, 's')) 207 | continue; 208 | int i; 209 | if (strcmp(modulepath, "[heap]") == 0) //not static enough to mark as a 'module' 210 | continue; 211 | 212 | // printf("%s\n", modulepath); 213 | 214 | if (strcmp(modulepath, "[vdso]") != 0) //temporary patch as to not rename vdso, because it is treated differently by the ce symbol loader 215 | { 216 | for (i = 0; modulepath[i]; i++) //strip square brackets from the name (conflicts with pointer notations) 217 | { 218 | if ((modulepath[i] == '[') || (modulepath[i] == ']')) 219 | modulepath[i] = '_'; 220 | } 221 | } 222 | 223 | i = ReadProcessMemory(pid, (void *)start, &magic, 4); 224 | if (i == 0) 225 | { 226 | // printf("%s is unreadable(%llx)\n", modulepath, start); 227 | continue; //unreadable 228 | } 229 | 230 | PModuleListEntry ml = (PModuleListEntry)malloc(sizeof(ModuleListEntry)); 231 | if (ret == nullptr) 232 | { 233 | ret = ml; 234 | } 235 | else 236 | { 237 | _ml->next_ptr = ml; 238 | _ml = ml; 239 | } 240 | ml->baseAddress = start; 241 | ml->moduleSize = stop - start; 242 | ml->moduleName = strdup(modulepath); 243 | ml->next_ptr = nullptr; 244 | 245 | _ml = ml; 246 | } 247 | return ret; 248 | } 249 | return nullptr; 250 | } 251 | 252 | #endif //MEMORY_H 253 | -------------------------------------------------------------------------------- /app/jni/jni_draw.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "Memory.h" 14 | #include "AOBScan.h" 15 | 16 | #define APP_PACKAGE_NAME "com.popcap.pvz" 17 | 18 | struct zombie_data 19 | { 20 | int x; 21 | int y; 22 | }; 23 | 24 | unsigned char pattern[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}; 25 | 26 | struct zombie_data zd[25]; 27 | 28 | void *checkApp(void *) 29 | { 30 | while (true) 31 | { 32 | if (find_pid(APP_PACKAGE_NAME) == -1) 33 | { 34 | exit(0); 35 | } 36 | sleep(5); 37 | // printf("heart beat\n"); 38 | } 39 | } 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | auto pid = find_pid(APP_PACKAGE_NAME); //获取pid 44 | if (pid == 0) 45 | { 46 | printf("Can't find pid\n"); 47 | return -1; 48 | } 49 | else 50 | { 51 | printf("pid:%d\n", pid); 52 | } 53 | 54 | //创建线程检测app是否退出 55 | pthread_t tidp; 56 | if (pthread_create(&tidp, NULL, checkApp, NULL) == -1) 57 | { 58 | printf("pthread_create error"); 59 | } 60 | 61 | int port = 53316; 62 | int udp_socket_fd = socket(AF_INET, SOCK_DGRAM, 0); 63 | if (udp_socket_fd == -1) 64 | { 65 | perror("socket failed!\n"); 66 | return -1; 67 | } 68 | //设置目的IP地址 69 | struct sockaddr_in dest_addr = {0}; 70 | dest_addr.sin_family = AF_INET; //使用IPv4协议 71 | dest_addr.sin_port = port; //设置接收方端口号 72 | dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //设置接收方IP 73 | 74 | PModuleListEntry ml = get_process_map(pid); //读取进程的模块信息,PModuleListEntry是一个链表 75 | PModuleListEntry ml_ = ml; 76 | 77 | while (true) 78 | { 79 | memset(zd,0,sizeof(zd)); 80 | int i = 0; 81 | ml = ml_; 82 | while (ml->next_ptr != nullptr) //循环所有的模块 83 | { 84 | if (!ml->moduleName[0]) //判断是否有模块名,注意,这个例子是没有模块名的. 85 | { 86 | int size = ml->moduleSize; 87 | unsigned char *target = (unsigned char *)malloc(size); 88 | unsigned char *target_ = target; 89 | int r = ReadProcessMemory(pid, (void *)ml->baseAddress, target, size); //读取内存 90 | if (r == 0) 91 | { 92 | goto lable; //unreadable 93 | } 94 | while (true) //循环搜索所有匹配到的特征地址 95 | { 96 | int offset = AOBScan(target, size, pattern, sizeof(pattern)); 97 | if (offset != -1) 98 | { 99 | target += offset + sizeof(pattern); 100 | size -= offset + sizeof(pattern); 101 | unsigned long long offset_ = target - target_ - sizeof(pattern); //这里是拿到偏移 102 | unsigned long long address = ml->baseAddress + offset_; //搜索到的目标进程的内存地址 103 | // printf("offset_:%llx\n", offset_); 104 | // printf("%llx\n", address); 105 | unsigned long long y = address + 0x4c;//僵尸的y坐标 106 | unsigned long long x = address + 0x38;//僵尸的x坐标 107 | // unsigned int data[] = {0x0}; 108 | // WriteProcessMemory(pid, (void *)y, (void *)data, sizeof(data) / sizeof(unsigned int)); //写内存 109 | 110 | int buffer; 111 | ReadProcessMemory(pid, (void *)x, &buffer, sizeof(buffer)); 112 | zd[i].x = buffer; 113 | ReadProcessMemory(pid, (void *)y, &buffer, sizeof(buffer)); 114 | zd[i].y = buffer; 115 | i++; 116 | continue; 117 | } 118 | break; 119 | } 120 | free(target_); 121 | } 122 | lable: 123 | ml = (PModuleListEntry)ml->next_ptr; 124 | } 125 | sendto(udp_socket_fd, zd, sizeof(zd), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); 126 | } 127 | close(udp_socket_fd); 128 | return 0; 129 | } -------------------------------------------------------------------------------- /app/libs/armeabi-v7a/libjni_draw.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/libs/armeabi-v7a/libjni_draw.so -------------------------------------------------------------------------------- /app/libs/x86/libjni_draw.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/libs/x86/libjni_draw.so -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/shocker/jnidraw/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.shocker.jnidraw; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.shocker.jnidraw", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.10.2) 7 | 8 | # Declares and names the project. 9 | 10 | project("jnidraw") 11 | 12 | # Creates and names a library, sets it as either STATIC 13 | # or SHARED, and provides the relative paths to its source code. 14 | # You can define multiple libraries, and CMake builds them for you. 15 | # Gradle automatically packages shared libraries with your APK. 16 | 17 | add_library( # Sets the name of the library. 18 | jnidraw 19 | 20 | # Sets the library as a shared library. 21 | SHARED 22 | 23 | # Provides a relative path to your source file(s). 24 | native-lib.cpp) 25 | 26 | # Searches for a specified prebuilt library and stores the path as a 27 | # variable. Because CMake includes system libraries in the search path by 28 | # default, you only need to specify the name of the public NDK library 29 | # you want to add. CMake verifies that the library exists before 30 | # completing its build. 31 | 32 | find_library( # Sets the name of the path variable. 33 | log-lib 34 | 35 | # Specifies the name of the NDK library that 36 | # you want CMake to locate. 37 | log) 38 | 39 | # Specifies libraries CMake should link to your target library. You 40 | # can link multiple libraries, such as libraries you define in this 41 | # build script, prebuilt third-party libraries, or system libraries. 42 | 43 | target_link_libraries( # Specifies the target library. 44 | jnidraw 45 | 46 | # Links the target library to the log library 47 | # included in the NDK. 48 | ${log-lib}) -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | float width_scale=1; 15 | float height_scale=1; 16 | 17 | #define ZOMBIE_WIDTH 115 18 | #define ZOMBIE_HEIGHT 170 19 | 20 | #define SCALE_WIDTH 1.44 21 | #define SCALE_HEIGHT 123 22 | 23 | #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "jni_draw", __VA_ARGS__)) 24 | 25 | 26 | struct zombie_data 27 | { 28 | int x; //僵尸x坐标 29 | int y; //僵尸y坐标,这里y为0,1,2,3,4,5.... 30 | }; 31 | 32 | int udp_socket_fd; 33 | //这个z_data就是接收udp数据的变量,默认一次接收25个数据 34 | struct zombie_data z_data[25]; 35 | 36 | void setup_udp(){ 37 | int port = 53316; 38 | udp_socket_fd = socket(AF_INET,SOCK_DGRAM,0); 39 | //设置udp非阻塞 40 | // int flag=fcntl(udp_socket_fd, F_GETFL, 0); 41 | // fcntl(udp_socket_fd, F_SETFL, flag | O_NONBLOCK); 42 | if(udp_socket_fd < 0 ) 43 | { 44 | perror("creat socket fail\n"); 45 | return; 46 | } 47 | struct sockaddr_in local_addr = {0}; 48 | local_addr.sin_family = AF_INET; //使用IPv4协议 49 | local_addr.sin_port = port; //网络通信都使用大端格式 50 | local_addr.sin_addr.s_addr = INADDR_ANY;//让系统检测本地网卡,自动绑定本地IP 51 | if(bind(udp_socket_fd,(struct sockaddr*)&local_addr,sizeof(local_addr)) < 0) 52 | { 53 | perror("bind fail:"); 54 | close(udp_socket_fd); 55 | return; 56 | } 57 | } 58 | 59 | 60 | 61 | extern "C" 62 | JNIEXPORT void JNICALL 63 | Java_com_shocker_jnidraw_OverlayView_Draw(JNIEnv *env, jclass clazz, jobject overlay_view, 64 | jobject canvas) { 65 | // TODO: implement Draw() 66 | jclass canvasView = env->GetObjectClass(overlay_view); 67 | jmethodID drawrect = env->GetMethodID(canvasView, "DrawRect", 68 | "(Landroid/graphics/Canvas;IIIIFFFFF)V"); 69 | for(int i=0;i< sizeof(z_data)/ sizeof(struct zombie_data);i++){ 70 | if (z_data[i].x<=0){ 71 | continue; 72 | } 73 | float zombie_x=z_data[i].x*SCALE_WIDTH*width_scale; 74 | float zombie_y=z_data[i].y*SCALE_HEIGHT*height_scale; 75 | env->CallVoidMethod(overlay_view, drawrect, canvas,255, 255,69, 0, 76 | (float)2.5,(float)zombie_x, (float)zombie_y, 77 | (float)zombie_x+ZOMBIE_WIDTH*width_scale, (float)zombie_y+ZOMBIE_HEIGHT*height_scale); 78 | } 79 | // env->CallVoidMethod(overlay_view, drawrect, canvas,255, 255,255, 255, 80 | // (float)2,(float)80, (float)0, (float)195, (float)170); 81 | } 82 | 83 | //阻塞接收root进程发来的数据 84 | void *recv_udp(void *) 85 | { 86 | while (true) 87 | { 88 | //理论上来说,这里是多线程访问同一数据,需要加锁,这里简化处理. 89 | recvfrom(udp_socket_fd, z_data, sizeof(z_data), 0, NULL, NULL); 90 | } 91 | } 92 | 93 | extern "C" 94 | JNIEXPORT void JNICALL 95 | Java_com_shocker_jnidraw_OverlayView_NativeInit(JNIEnv *env, jobject thiz) { 96 | // TODO: implement NativeInit() 97 | //初始化udp 98 | setup_udp(); 99 | //创建一个线程专门来读取udp数据 100 | pthread_t tidp; 101 | if (pthread_create(&tidp, NULL, recv_udp, NULL) == -1) 102 | { 103 | printf("pthread_create error"); 104 | } 105 | } 106 | extern "C" 107 | JNIEXPORT void JNICALL 108 | Java_com_shocker_jnidraw_OverlayView_SetWidthScale(JNIEnv *env, jobject thiz, jint width) { 109 | // TODO: implement SetWidthScale() 110 | //设置缩放倍率,测试在1280*720做的,不同分辨率要做不同处理 111 | width_scale=(float)width/1280; 112 | } 113 | extern "C" 114 | JNIEXPORT void JNICALL 115 | Java_com_shocker_jnidraw_OverlayView_SetHeightScale(JNIEnv *env, jobject thiz, jint height) { 116 | // TODO: implement SetHeightScale() 117 | //同上 118 | height_scale=(float)height/720; 119 | // height_scale=width_scale; 120 | } -------------------------------------------------------------------------------- /app/src/main/java/com/shocker/jnidraw/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.shocker.jnidraw; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.ActivityInfo; 8 | import android.graphics.PixelFormat; 9 | import android.net.Uri; 10 | import android.os.Build; 11 | import android.os.Bundle; 12 | import android.provider.Settings; 13 | import android.util.DisplayMetrics; 14 | import android.view.Display; 15 | import android.view.Gravity; 16 | import android.view.View; 17 | import android.view.WindowManager; 18 | import android.widget.TextView; 19 | 20 | import com.shocker.jnidraw.databinding.ActivityMainBinding; 21 | 22 | import java.io.OutputStream; 23 | 24 | public class MainActivity extends AppCompatActivity { 25 | 26 | // Used to load the 'jnidraw' library on application startup. 27 | static { 28 | System.loadLibrary("jnidraw"); 29 | } 30 | 31 | 32 | public int getLayoutType() { 33 | int LAYOUT_FLAG; 34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 35 | LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 36 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 37 | LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE; 38 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 39 | LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE; 40 | } else { 41 | LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 42 | } 43 | return LAYOUT_FLAG; 44 | } 45 | 46 | //申请悬浮窗权限 47 | void getFloatPermission(){ 48 | if (android.os.Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) { //Android M Or Over 49 | Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())); 50 | startActivityForResult(intent, 123); 51 | } 52 | } 53 | 54 | 55 | //创建root进程,用udp通信 56 | public void StartSuProcess() throws Exception{ 57 | Process p = Runtime.getRuntime().exec("su"); 58 | OutputStream os = p.getOutputStream(); 59 | p.getErrorStream(); 60 | String str =getBaseContext().getApplicationInfo().nativeLibraryDir+"/libjni_draw.so"; 61 | os.write((str + "\n").getBytes()); 62 | os.write("exit\n".getBytes()); 63 | os.flush(); 64 | os.close(); 65 | } 66 | 67 | @Override 68 | protected void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | 71 | //申请悬浮窗权限 72 | getFloatPermission(); 73 | try { 74 | StartSuProcess(); 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | //获取屏幕宽高,适配不同宽高的屏幕 79 | DisplayMetrics outMetrics = new DisplayMetrics(); 80 | getWindowManager().getDefaultDisplay().getMetrics(outMetrics); 81 | int widthPixels = outMetrics.widthPixels; 82 | int heightPixels = outMetrics.heightPixels; 83 | 84 | WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 85 | OverlayView overlayView = new OverlayView(this,widthPixels,heightPixels); 86 | //设置悬浮窗的一些属性 87 | final WindowManager.LayoutParams params = new WindowManager.LayoutParams( 88 | getLayoutType(), 89 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 90 | PixelFormat.TRANSLUCENT); 91 | if (Build.VERSION.SDK_INT >= 28) { 92 | params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES ; 93 | } 94 | //添加悬浮窗 95 | windowManager.addView(overlayView, params); 96 | } 97 | 98 | } -------------------------------------------------------------------------------- /app/src/main/java/com/shocker/jnidraw/OverlayView.java: -------------------------------------------------------------------------------- 1 | package com.shocker.jnidraw; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.PorterDuff; 8 | import android.view.View; 9 | 10 | class OverlayView extends View { 11 | public static native void Draw(OverlayView overlayView, Canvas canvas); 12 | private native void NativeInit(); 13 | private native void SetWidthScale(int width); 14 | private native void SetHeightScale(int height); 15 | 16 | Paint mStrokePaint; 17 | 18 | 19 | public OverlayView(Context context, int widthPixels, int heightPixels) { 20 | super(context); 21 | //初始化Paint 22 | Init(); 23 | //jni层初始化 24 | NativeInit(); 25 | //传入当前宽高,在jni里设置出缩放比例 26 | SetWidthScale(widthPixels); 27 | SetHeightScale(heightPixels); 28 | } 29 | 30 | 31 | @Override 32 | protected void onDraw(Canvas canvas) { 33 | // super.onDraw(canvas); 34 | // DrawRect(canvas,255, 255, 255, 255,1,80,80,550,600); 35 | Draw(this,canvas); 36 | invalidate(); 37 | } 38 | 39 | public void DrawRect(Canvas cvs, int a, int r, int g, int b, float stroke, float x, float y, float width, float height) { 40 | mStrokePaint.setStrokeWidth(stroke); 41 | mStrokePaint.setColor(Color.rgb(r, g, b)); 42 | mStrokePaint.setAlpha(a); 43 | cvs.drawRect(x, y, width, height, mStrokePaint); 44 | } 45 | 46 | 47 | public void Init() { 48 | mStrokePaint = new Paint(); 49 | mStrokePaint.setStyle(Paint.Style.STROKE); 50 | mStrokePaint.setAntiAlias(true); 51 | mStrokePaint.setColor(Color.rgb(0, 0, 0)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | jnidraw 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/test/java/com/shocker/jnidraw/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.shocker.jnidraw; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | dependencies { 8 | classpath "com.android.tools.build:gradle:7.0.4" 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | task clean(type: Delete) { 16 | delete rootProject.buildDir 17 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Feb 04 20:15:48 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /img/image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PShocker/Android_float_view_draw/61e54c2d3a856ea006ce32151f54b721af346c44/img/image.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 3 | repositories { 4 | google() 5 | mavenCentral() 6 | jcenter() // Warning: this repository is going to shut down soon 7 | } 8 | } 9 | rootProject.name = "jnidraw" 10 | include ':app' 11 | --------------------------------------------------------------------------------