├── .gitignore ├── DrawGGDoc.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── gg96.jar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ ├── Thousand_Dust │ │ ├── DevInfo.java │ │ ├── DrawView.java │ │ ├── MyAccessibilityService.java │ │ ├── MyWindowManager.java │ │ ├── ScriptLib.java │ │ ├── Tools.java │ │ ├── canvas │ │ │ ├── BitmapLib.java │ │ │ ├── CanvasLib.java │ │ │ ├── PaintLib.java │ │ │ └── ViewLib.java │ │ ├── luaj │ │ │ ├── LuaBitmap.java │ │ │ ├── LuaCanvas.java │ │ │ ├── LuaPaint.java │ │ │ └── LuaView.java │ │ └── socket │ │ │ ├── LuaServerSocket.java │ │ │ └── LuaSocket.java │ └── com │ │ └── gg │ │ └── function │ │ └── MainActivity.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.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 │ └── xml │ ├── accessibility_config.xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── 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 | -------------------------------------------------------------------------------- /DrawGGDoc.md: -------------------------------------------------------------------------------- 1 | ## DrawGG函数教程 2 | 这里是DrawGG函数教程 3 | 4 | 简介:基于gg luaj包编写的扩展函数,包含绘制函数等。也可以用在官方luaj包上,只需要改一下Tools类的getContext方法即可。 5 | 6 | 7 | **提示:由于以下函数比较占内存,编写代码时建议赋值为局部变量。可以有效加快脚本运行速度** 8 | 9 | **[函数演示效果代码和视频](#_382)** 10 | **[源码和成品](#_454)** 11 | 12 | @[TOC](函数教程) 13 | 14 | 下面开始函数教程: 15 | 16 | **v1.1新增函数** 17 | 由于android12以上系统限制,使用穿透触摸事件的悬浮窗需要无障碍权限,但无障碍由于无障碍的不便捷性,新增了对非无障碍的支持 18 | 在脚本开头调用如下函数,即可在android12及以上系统免于开启无障碍 19 | 20 | ```lua 21 | --强制禁用android12以上的无障碍申请 22 | disDrawAcc() 23 | ``` 24 | 原理:将悬浮窗的透明度强制锁定为0.8f,代价是所有绘制的内容透明度都会降低 25 | 26 | **-----下面是画笔函数-----** 27 | # 画笔函数 28 | **1、新建画笔:newPaint** 29 | 函数作用:新建并返回一个画笔 30 | 31 | ```lua 32 | -- 新建画笔 33 | paint = newPaint() 34 | ``` 35 | ## 设置抗锯齿 36 | **1.1、setAntialias** 37 | 函数作用:开启和关闭画笔的抗锯齿功能。参数:true或false 38 | true为开启抗锯齿,false为关闭抗锯齿。开启抗锯齿后会增加计算量。画笔默认关闭抗锯齿。 39 | 开启抗锯齿后绘制内容不会出现锯齿,更加圆润。 40 | 下图仔细看就能看出开了抗锯齿和没开的区别: 41 | ![画笔开了抗锯齿和没开的区别](https://img-blog.csdnimg.cn/20200921201937320.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1OTI1MjMw,size_16,color_FFFFFF,t_70#pic_center) 42 | 43 | 示例: 44 | 45 | ```lua 46 | -- 初始化画笔 47 | paint = newPaint() 48 | paint:setAntialias(true) -- 开启抗锯齿 49 | ``` 50 | ## 设置颜色 51 | **1.2、setColor** 52 | 函数作用:设置画笔画出的内容颜色。参数:ARGB十六进制字符串 53 | 比如:#FF998877,FF表示的是透明度,FF不透明,00未完全透明。99为红色深浅度,88为绿色深浅度,77为蓝色深浅度。透明值不写默认为FF。 54 | 详情请百度。 55 | 56 | 示例: 57 | 58 | ```lua 59 | -- 初始化画笔 60 | paint = newPaint() 61 | paint:setColor("#FFFFFF") -- 设置画笔白色 62 | ``` 63 | ## 设置样式 64 | **1.3、设置画笔样式:setStyle** 65 | 函数作用:设置画笔画出的内容样式。参数:画笔样式 66 | 样式值分别有:**0**:描边,**1**:填充,**2**:描边并填充; 67 | "**描边**":描边, "**填充**":填充,"**描边并填充**":描边并填充 68 | 示例: 69 | 70 | ```lua 71 | -- 初始化画笔 72 | paint = newPaint() 73 | paint:setStyle(0) -- 设置画笔样式为描边 74 | --或者 75 | paint:setStyle("描边") 76 | ``` 77 | ## 设置画笔画出的字符串大小 78 | **1.4、setTextSize** 79 | 函数作用:设置画笔画出来的文本大小。参数:大小值 80 | 示例: 81 | 82 | ```lua 83 | -- 初始化画笔 84 | paint = newPaint() 85 | paint:setTextSize(5) -- 设置画笔绘制的文本大小为5 86 | ``` 87 | ## 设置画笔笔触宽度 88 | **1.5、setWidth** 89 | 函数作用:设置画笔笔触宽度。参数:宽度大小值,参数类型:数字。返回值:无 90 | 画笔笔触默认值为:1(应该是,我也不太清楚) 91 | 示例: 92 | 93 | ```lua 94 | -- 初始化画笔 95 | paint = newPaint() 96 | paint:setWidth(10) -- 设置笔触宽度为10 97 | ``` 98 | **----------------------好了,以上就是画笔的所有函数了------------------------** 99 | **下面是图片的函数** 100 | # 图片函数 101 | **2.1、从文件加载图片:loadFile** 102 | 函数作用:新建一个图片对象并返回。参数:(图片文件路径)或(图片字符串),参数类型:文件路径 或 文件字符串 103 | 示例: 104 | 105 | ```lua 106 | -- 新建图片方式一 107 | bitmap = loadFile("图片文件路径") 108 | ``` 109 | ## 从LuaString加载图片 110 | **2.2、load** 111 | 函数作用:从lua的字符串中加载图片 112 | 和从文件加载图片函数类似,我就不多说了。 113 | 示例: 114 | 115 | ```lua 116 | -- 新建图片方式二,从LuaString读取图片 117 | file = io.open("图片文件路径", "r") 118 | content = file:read("*a") 119 | file:close() 120 | bitmap = load(content) 121 | ``` 122 | ## 设置图片的宽 123 | **2.3、setWidth** 124 | 函数作用:按比例将图片缩放到设置的宽。参数:要设置的宽。 125 | 示例: 126 | 127 | ```lua 128 | bitmap = loadFile("图片文件路径") 129 | bitmap:setWidth(500) --将图片的宽设置为500像素 130 | ``` 131 | ## 设置图片的高 132 | **2.4、setHeight** 133 | 函数作用:按比例将图片缩放到设置的高。参数:要设置的高。 134 | 示例: 135 | 136 | ```lua 137 | bitmap = loadFile("图片文件路径") 138 | bitmap:setHeight(500) --将图片的高设置为500像素 139 | ``` 140 | 141 | ## 获取图片的宽高 142 | **2.6、getWH** 143 | 函数作用:获取图片的宽和高 144 | 示例: 145 | 146 | ```lua 147 | bitmap = loadFile("图片文件路径") 148 | -- 获取图片宽搞 149 | wh = bitmap:getWH() 150 | print("宽为:"..wh[1].."高为:"..wh[2]) 151 | ``` 152 | ## 删除图片 153 | **2.8、remove** 154 | 函数作用:删除图片,释放内存。当某个图片对象不再需要使用时调用此方法删除图片 155 | 调用次函数后的Bitma对象将无法再继续使用。 156 | 示例: 157 | 158 | ```lua 159 | bitmap = loadFile("图片文件路径") 160 | --删除图片,并释放内存 161 | bitmap:remove() 162 | ``` 163 | 164 | **———————————以上就是图片函数的所有内容了—————————————** 165 | **下面是画布函数,也是最主要的函数** 166 | # 画布函数 167 | 提示:画布不需要手动创建,写一个带有一个参数的方法。用view:show调用此方法就会传入画布(后面有教程)。每次传入的画布都是不同的,所以不需要把画布保存 168 | 示例: 169 | 170 | ```lua 171 | --带有一个参数的方法,用来接收画布并进行绘制操作 172 | function onDraw(canvas) --方法名随便写,没有要求 173 | --创建画笔 174 | paint = newPaint() 175 | --使用传入的画布参数进行绘制一个圆的操作 176 | canvas:drawCircle(200,200,100,paint) --在坐标(x200,y200)的地方为圆心画一个半径为100像素的圆 177 | end 178 | --View函数,后面有教程 179 | view = newView() 180 | view:show(onDraw) -- 显示绘制并自动刷新 181 | sleep(1000) --休眠1000ms,避免脚本运行结束后绘制内容被系统回收 182 | view:close() 183 | ``` 184 | 效果图 185 | ## 绘制线段 186 | **3.1、drawLine** 187 | 函数作用:在屏幕上绘制一条线段。参数(线段开头x坐标,y坐标,线段结尾x坐标,y坐标)。 188 | ```lua 189 | paint = newPaint() 190 | canvas:drawLine(0,0,300,200,paint) 191 | ``` 192 | 下面的绘制函数也是这样使用自定义画笔进行绘制内容 193 | ## 绘制多条线段 194 | **3.2、drawLines** 195 | 函数作用:绘制多条线段。参数:{线段开头x坐标,y坐标,结尾x坐标,y坐标,......} 196 | 参数个数无限制 197 | ```lua 198 | -- 初始化画布 199 | paint = newPaint() 200 | canvas:drawLines({50, 600, 400, 600, 400, 600, 400, 50,400, 50, 50, 50, 50, 50, 50, 600}, paint) 201 | ``` 202 | 执行后就会出现如下效果。 203 | 204 | ![drawLines解释](https://img-blog.csdnimg.cn/20200922183947851.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1OTI1MjMw,size_16,color_FFFFFF,t_70#pic_center) 205 | 以此类推,参数个数无限制! 206 | 如果实在不会的话,那就跳过吧!你们应该用不上 207 | ## 绘制矩形 208 | **3.3、drawRect** 209 | 函数作用:绘制一个矩形。参数:({矩形左上角x坐标,y坐标,矩形右下角x坐标,y坐标},画笔)。 210 | 示例: 211 | 212 | ```lua 213 | -- 初始化canvas 214 | paint = newPaint() 215 | canvas:drawRect({100,100,400,200}, paint) 216 | ``` 217 | 218 | ## 绘制圆 219 | **3.4、drawCircle** 220 | 函数作用:绘制一个圆。参数:(圆心x坐标,y坐标,圆的半径,画笔)。 221 | 222 | ```lua 223 | -- 初始化画布 224 | paint = newPaint() 225 | canvas:drawCorcle(400,400,200, paint) 226 | ``` 227 | ## 绘制背景颜色 228 | **3.5、drawColor** 229 | 函数作用:绘制一个颜色作为背景。参数:颜色值。参数类型:字符串。 230 | 此方法不接收画笔对象! 231 | 示例: 232 | 233 | ```lua 234 | -- 绘制一个半透明的白色作为背景 235 | paint = newPaint() 236 | canvas.drawColor("#80FFFFFF") 237 | ``` 238 | ## 绘制文本 239 | **3.5、drawText** 240 | 函数作用:绘制一个文本。参数:(要绘制的字符串,要绘制的左上角x坐标,y坐标,画笔)。 241 | 示例: 242 | 243 | ```lua 244 | -- 初始化画布 245 | paint = newPaint() 246 | canvas.drawText("绘制测试", 200,200, paint) 247 | ``` 248 | ## 绘制Bitmap图片 249 | **3.6、draweBitmap** 250 | 函数作用:绘制一个Bitmap图片。参数:(bitmap对象,x坐标,y坐标,画笔)。 251 | 示例: 252 | 253 | ```lua-- 初始化bitmap图片 254 | paint = newPaint() 255 | bitmap = loadFile("图片文件路径") 256 | canvas.drawBitmap(bitmap, 200,200, paint) 257 | ``` 258 | 259 | ## 绘制圆弧 260 | **3.8、drawArc** 261 | 函数作用:绘制一个圆弧。参数:({**圆弧的绘制范围左上角x坐标,y坐标,右下角x坐标,y坐标**},圆弧开始角度,经过角度,是否经过圆心,画笔)。。 262 | 这个相对比较复杂,看不懂可以跳过! 263 | 示例: 264 | 265 | ```lua 266 | -- 初始化画布 267 | paint = newPaint() 268 | canvas:drawArc({100,100,400,400},0,90,false, paint) 269 | ``` 270 | ## 裁剪绘制内容 271 | **3.9、clipRect** 272 | 函数作用:将绘制范围裁剪为一个四边形。只有在四边形内的绘制内容才能显示。参数和drawRect一样:({{四边形左上角x坐标,y坐标,右下角x坐标,y坐标},画笔) 273 | 示例: 274 | 275 | ```lua 276 | paint = newPaint() 277 | canvas:clipRect({100,100,200,200}, paint) 278 | ``` 279 | ## 移动画布 280 | **3.10、translate** 281 | 函数作用:移动画布原点。参数:原点x坐标,y坐标 282 | 画布原点默认为x:0, y:0 283 | 示例: 284 | 285 | ```lua 286 | canvas:translate(100,100) 287 | ``` 288 | ## 旋转画布 289 | **3.11、rotate** 290 | 函数作用:将画布顺时针旋转。参数(旋转角度)或者(旋转角度,旋转中心x坐标,y坐标) 291 | 示例: 292 | 293 | ```lua 294 | canvas:rotate(90) --以画布原点为中心顺时针旋转90度 295 | canvas:rotate(90, 300, 300) --以坐标(x:300,y:300)为中心顺时针旋转90度 296 | ``` 297 | ## 保存画布状态 298 | **3.12、save** 299 | 函数作用:保存画布的当前状态。用于对画布状态进行自定义前保存状态,配合恢复状态函数使用。 300 | ## 恢复画布状态 301 | **3.13、restore** 302 | 函数作用:将上一次保存的画布状态恢复。用于配合保存画布状态函数使用。 303 | 示例: 304 | ```lua 305 | canvas:save() --保存画布状态 306 | canvas:translte(200,200) --移动画布原点到x:200,y:200 307 | canvas:drawRect({0,0,100,100}, newPaint()) --绘制一个四边形 308 | canvas:restore() --恢复状态 309 | ``` 310 | # 视图函数 311 | 视图函数是绘制内容的载体,用于加载显示和刷新绘制内容 312 | 313 | ## 新建视图 314 | **1.1、newView()** 315 | 函数作用:新建一个视图对象并返回 316 | 示例: 317 | 318 | ```lua 319 | view = newView() 320 | ``` 321 | ## 显示绘制 322 | **1.2、show** 323 | 函数作用:加载Lua绘制方法。并进行初始显示。参数:Lua的绘制方法, 帧数(可选) 324 | 一个视图对象只能使用一个Lua函数。下一次show将会把上一次的覆盖 325 | 326 | **注意:绘制方法内不应进行耗时操作,因为绘制方法是在主线程被调用,执行的耗时直接决定了帧率的上限!** 327 | 示例: 328 | ```lua 329 | paint = newPaint() 330 | function onDraw(canvas) --方法名随意,没有要求。必须要有一个参数用来接收画布 331 | --特别注意:绘制方法内不应该进行耗时操作和创建视图、画笔、图片等。会造成性能问题,应当在绘制方法外部先声明所需的变量 332 | canvas:drawCircle(200,200,100, paint) --画圆 333 | end 334 | view = newView() --新建视图对象 335 | view:show(onDraw) --调用onDraw方法进行绘制,并进行初始显示 336 | --或者如下,增加有一个帧率参数,就会自动以60帧刷新绘制 337 | view:show(onDraw, 60) 338 | ``` 339 | 以上代码,在调用了view:show(onDraw)后,系统将会自动的多次调用onDraw方法,调用频率取决于帧率,所以绘制的内容也就是canvas函数需要写在onDraw(绘制方法)方法中。注意:onDraw(绘制方法) 中不要调用newPaint函数,加载图片,休眠等耗时操作。会影响刷新率 340 | ## 手动刷新绘制 341 | **1.3、invalidate** 342 | 函数作用:调用已经show的方法进行刷新绘制。 343 | 注:调用show函数后会自动刷新绘图,特殊情况下才需要使用invalidate刷新绘图 344 | 示例: 345 | 346 | ```lua 347 | view = newView() 348 | i = 0 349 | paint = newPaint() 350 | view:show(function(canvas) 351 | canvas:drawCircle(i,i,50,paint()) 352 | end) --将匿名方法作为绘制函数 353 | 354 | for i = 1,200 do 355 | i = i+2 356 | invalidate() 357 | sleep(20) 358 | end 359 | ``` 360 | ## 删除视图中的绘制内容 361 | **1.4、close** 362 | 函数作用:删除视图中的所有绘制内容。 363 | 示例: 364 | 365 | ```lua 366 | view = newView() 367 | view:show(function(canvas) 368 | --绘制操作 369 | end) 370 | view:close() 371 | ``` 372 | ## 删除所有绘制视图 373 | **1.5、removeAll** 374 | 375 | ```lua 376 | view = newView() 377 | view:show(function(canvas) 378 | --绘制操作 379 | end) 380 | removeAllView() 381 | ``` 382 | 383 | # 代码演示和视频 384 | ```lua 385 | --强制禁用android12以上的无障碍申请 386 | disDrawAcc() 387 | 388 | --创建画笔 389 | paint = newPaint() 390 | --画笔红色 391 | paint:setColor("#FF0000") 392 | --画笔笔触宽度10像素 393 | paint:setWidth(10) 394 | --创建绘制载体视图 395 | view = newView() 396 | 397 | --绘制方法 398 | y = 0 399 | function onDraw(canvas) 400 | --移动画布原点 401 | canvas:translate(200, y) 402 | --画圆 403 | canvas:drawCircle(0, 100, 100, paint) 404 | --画矩形 405 | canvas:drawRect({200, 0, 400, 200}, paint) 406 | y = y + 5 407 | end 408 | 409 | --以60帧刷新率显示绘制 410 | view:show(onDraw, 60) 411 | gg.sleep(3000) 412 | ``` 413 | 414 | 415 | [video(video-oxoe0UmK-1679757389544)(type-csdn)(url-https://live.csdn.net/v/embed/245908)(image-https://video-community.csdnimg.cn/vod-84deb4/f6ac6e502c05434b9270fd72f8a3abb4/snapshots/bab47786f4a543658f2fe0d74e77ff8a-00001.jpg?auth_key=4819537868-0-0-b429d81f07b93211f3519377af86f5cb)(title-代码演示效果)] 416 | 417 | 418 | 419 | # 其他函数 420 | ## 多线程函数 421 | **1.1、thread** 422 | 函数作用:启动新线程调用Lua方法 423 | 多线程函数有个bug暂时无法修复。不能多个线程同时调用sleep函数。否则会报错。 424 | 示例: 425 | 426 | ```lua 427 | function run() 428 | --要在新线程里执行的内容 429 | for i = 1,1000 do 430 | print(i) 431 | end 432 | end 433 | thread(run) 434 | ---------------------------------------- 435 | --或者使用匿名方法 436 | thread(function() 437 | --要在新线程中执行的内容 438 | for i = 1, 1000 do 439 | print(i) 440 | end 441 | end) 442 | ``` 443 | 444 | ## 获取屏幕分辨率 445 | **1.4、getWH** 446 | 函数作用:获取屏幕可显示范围的长和宽 447 | 示例: 448 | 449 | ```lua 450 | wh = getWH() 451 | print("屏幕的宽:"..wh[1]) 452 | print("屏幕的高为:"..wh[2]) 453 | ``` 454 | 455 | ## 源码和成品 456 | 以上就是全部内容了,项目源码地址如下: 457 | gg96版:https://github.com/gnahz77/GG-CustomizeFunction 458 | gg101版:https://github.com/gnahz77/GG-CustomizeFunction-101 459 | 成品下载地址也在里面 460 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GG-CustomizeFunction 2 | 对GameGuardian进行自定义的函数,目前只添加绘制函数(在悬浮窗对View进行自定义绘制)和多线程函数。如需运行在非gg luaj上,只需要修改Thousand_Dust/Tools.getContext()方法即可。 3 | ## 制作不易给个☆star吧,谢谢啦!!! 4 | 5 | # gg版本 6 | 此项目基于96版gg的jar进行编写,需要101版移步: 7 | https://github.com/Thousand-Dust/GG-CustomizeFunction-101 8 | 代码不同但函数库效果是一样的 9 | 10 | ## [函数文档](DrawGGDoc.md) 11 | 12 | # 给其他gg添加此函数库教程 13 | 视频录制者文艺:https://b23.tv/LcXSQap 14 | 15 | # 成品安装包 16 | https://wwt.lanzoul.com/b02vn048j 17 | 密码:draw 18 | ## [releases](https://github.com/Thousand-Dust/GG-CustomizeFunction/releases) 19 | 20 | 21 | # 测试脚本 22 | 23 | ```lua 24 | --强制禁用android12以上的无障碍申请 25 | disDrawAcc() 26 | 27 | --创建画笔 28 | paint = newPaint() 29 | --画笔红色 30 | paint:setColor("#FF0000") 31 | --画笔笔触宽度10像素 32 | paint:setWidth(10) 33 | --创建绘制载体视图 34 | view = newView() 35 | 36 | --绘制方法 37 | y = 0 38 | function onDraw(canvas) 39 | --移动画布原点 40 | canvas:translate(200, y) 41 | --画圆 42 | canvas:drawCircle(0, 100, 100, paint) 43 | --画矩形 44 | canvas:drawRect({200, 0, 400, 200}, paint) 45 | y = y + 5 46 | end 47 | 48 | --以60帧刷新率显示绘制 49 | view:show(onDraw, 60) 50 | gg.sleep(3000) 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdk 31 7 | 8 | defaultConfig { 9 | applicationId "com.gg.function" 10 | minSdk 22 11 | targetSdk 31 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | 32 | implementation 'androidx.appcompat:appcompat:1.3.0' 33 | implementation 'com.google.android.material:material:1.4.0' 34 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 35 | implementation files('libs\\gg96.jar') 36 | testImplementation 'junit:junit:4.13.2' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 39 | } -------------------------------------------------------------------------------- /app/libs/gg96.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/libs/gg96.jar -------------------------------------------------------------------------------- /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/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/DevInfo.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | public class DevInfo 4 | { 5 | public static String getVersion() { 6 | return "1.0"; 7 | } 8 | 9 | public static String getAuthor(){ 10 | return "多线程、绘制函数开发者信息:\n" + 11 | "源码链接: https://github.com/Thousand-Dust/GG-CustomizeFunction 给个Star谢谢\n" + 12 | "开发者: 执念;" + 13 | "特别鸣谢: 小五"; 14 | } 15 | 16 | public static String getUpdateTime() 17 | { 18 | return "2022/10/16"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/DrawView.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | 7 | import luaj.Globals; 8 | import Thousand_Dust.luaj.LuaCanvas; 9 | import luaj.LuaFunction; 10 | 11 | import android.graphics.Paint; 12 | import android.util.Log; 13 | import android.view.View; 14 | 15 | import androidx.annotation.NonNull; 16 | 17 | /** 18 | * @author Thousand-Dust 19 | */ 20 | public class DrawView extends View { 21 | 22 | private Globals globals; 23 | private final Refresh refresh = new Refresh(); 24 | 25 | private Paint paint; 26 | //缓冲图 27 | private Bitmap bufBitmap; 28 | //缓冲画布 29 | public Canvas canvas; 30 | public LuaCanvas luaCanvas; 31 | private LuaFunction drawFun; 32 | private boolean isRemove = false; 33 | 34 | public DrawView(Context context, Globals globals) { 35 | super(context); 36 | this.globals = globals; 37 | paint = new Paint(); 38 | int[] wh = Tools.getWH(context); 39 | //防canvas的绘制内容画到缓冲图上 40 | bufBitmap = Bitmap.createBitmap(wh[0], wh[1], Bitmap.Config.ARGB_8888); 41 | canvas = new Canvas(bufBitmap); 42 | luaCanvas = LuaCanvas.valueOf(canvas); 43 | } 44 | 45 | public void setDrawFun(LuaFunction drawFun) { 46 | this.drawFun = drawFun; 47 | } 48 | 49 | @Override 50 | protected void onDraw(Canvas canvas) { 51 | canvas.drawBitmap(bufBitmap, 0, 0, paint); 52 | } 53 | 54 | @Override 55 | public void invalidate() { 56 | //将bitmap清空 57 | bufBitmap.eraseColor(0); 58 | if (drawFun != null) { 59 | canvas.save(); 60 | drawFun.call(luaCanvas); 61 | canvas.restore(); 62 | } 63 | super.invalidate(); 64 | } 65 | 66 | @Override 67 | public void postInvalidate() { 68 | super.postInvalidate(); 69 | } 70 | 71 | @Override 72 | protected void onDetachedFromWindow() { 73 | super.onDetachedFromWindow(); 74 | close(); 75 | } 76 | 77 | public void start(int fps) { 78 | refresh.fps = fps; 79 | if (!refresh.isStart) { 80 | new Thread(refresh).start(); 81 | } 82 | } 83 | 84 | public void close() { 85 | refresh.isStart = false; 86 | } 87 | 88 | class Refresh implements Runnable { 89 | private boolean isStart = false; 90 | private int fps = 60; 91 | 92 | @Override 93 | public void run() { 94 | isStart = true; 95 | //每帧间隔时间 96 | long interval = 1000 / fps; 97 | try { 98 | while (isStart) { 99 | //按设置帧率刷新画面 100 | long startTime = System.currentTimeMillis(); 101 | DrawView.this.postInvalidate(); 102 | long timeConsuming = System.currentTimeMillis() - startTime; 103 | if (timeConsuming < interval) { 104 | Thread.sleep(interval - timeConsuming); 105 | } 106 | } 107 | } catch (Exception e) { 108 | e.printStackTrace(globals.STDOUT); 109 | android.ext.Tools.showToast("error: " + e.getMessage()); 110 | } finally { 111 | if (isStart) { 112 | isStart = false; 113 | } 114 | } 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/MyAccessibilityService.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | import android.accessibilityservice.AccessibilityService; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.util.Log; 7 | import android.view.accessibility.AccessibilityEvent; 8 | 9 | /** 10 | * @author Thousand-Dust 11 | */ 12 | public class MyAccessibilityService extends AccessibilityService { 13 | 14 | @Override 15 | protected void onServiceConnected() { 16 | super.onServiceConnected(); 17 | MyWindowManager.newInstance(this); 18 | } 19 | 20 | @Override 21 | public boolean onUnbind(Intent intent) { 22 | if (!MyWindowManager.isInstanceEmpty()) { 23 | MyWindowManager.destInstance(); 24 | } 25 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { 26 | MyWindowManager.newInstance(Tools.getContext()); 27 | } 28 | return super.onUnbind(intent); 29 | } 30 | 31 | @Override 32 | public void onAccessibilityEvent(AccessibilityEvent event) { 33 | 34 | } 35 | 36 | @Override 37 | public void onInterrupt() { 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/MyWindowManager.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | import android.content.Context; 4 | import android.graphics.PixelFormat; 5 | import android.os.Build; 6 | import android.os.Handler; 7 | import android.os.Looper; 8 | import android.view.Gravity; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.view.WindowManager; 12 | import android.widget.LinearLayout; 13 | 14 | import luaj.LuaError; 15 | 16 | /** 17 | * @author Thousand-Dust 18 | */ 19 | public class MyWindowManager { 20 | 21 | private static MyWindowManager mWm; 22 | private static float alpha = 1f; 23 | 24 | public static final float MAXIMUM_OBSCURING_OPACITY = 0.8f; 25 | 26 | public static void newInstance(Context context) { 27 | if (mWm == null) { 28 | mWm = new MyWindowManager(context); 29 | } 30 | } 31 | 32 | public static boolean isInstanceEmpty() { 33 | return mWm == null; 34 | } 35 | 36 | public static MyWindowManager getInstance() { 37 | if (mWm == null) { 38 | throw new LuaError("悬浮窗未初始化,可能是无障碍功能可能未开启"); 39 | } 40 | return mWm; 41 | } 42 | 43 | public static void destInstance() { 44 | mWm.removeAllViews(); 45 | mWm.wm.removeView(mWm.viewGroup); 46 | mWm = null; 47 | System.gc(); 48 | } 49 | 50 | public static void setAlpha(float alpha) { 51 | MyWindowManager.alpha = alpha; 52 | if (!isInstanceEmpty()) { 53 | //悬浮窗已实例化,更新悬浮窗透明度 54 | mWm.lp.alpha = alpha; 55 | mWm.handler.post(() -> { 56 | mWm.wm.updateViewLayout(mWm.viewGroup, mWm.lp); 57 | }); 58 | } 59 | } 60 | 61 | public static float getAlpha() { 62 | return alpha; 63 | } 64 | 65 | private Handler handler = new Handler(Looper.getMainLooper()); 66 | private WindowManager wm; 67 | private WindowManager.LayoutParams lp; 68 | private ViewGroup viewGroup; 69 | 70 | private MyWindowManager(Context context) { 71 | initView(context); 72 | initWindow(context); 73 | } 74 | 75 | private void initView(Context context) { 76 | viewGroup = new LinearLayout(context); 77 | } 78 | 79 | private void initWindow(Context context) { 80 | //悬浮窗类型 81 | int type; 82 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { 83 | type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 84 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && alpha > MAXIMUM_OBSCURING_OPACITY) { 85 | type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 86 | } else { 87 | type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 88 | } 89 | 90 | wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 91 | lp = new WindowManager.LayoutParams( 92 | ViewGroup.LayoutParams.MATCH_PARENT, 93 | ViewGroup.LayoutParams.MATCH_PARENT, 94 | type, 95 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 96 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | 97 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | 98 | WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW, 99 | PixelFormat.RGBA_8888 100 | ); 101 | lp.alpha = alpha; 102 | lp.gravity = Gravity.TOP | Gravity.LEFT; 103 | 104 | wm.addView(viewGroup, lp); 105 | } 106 | 107 | public synchronized void addView(View view) { 108 | handler.post(() -> viewGroup.addView(view)); 109 | } 110 | 111 | public synchronized void removeView(View view) { 112 | handler.post(() -> viewGroup.removeView(view)); 113 | } 114 | 115 | public synchronized void removeAllViews() { 116 | handler.post(() -> viewGroup.removeAllViews()); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/ScriptLib.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | import Thousand_Dust.canvas.BitmapLib; 4 | import Thousand_Dust.canvas.CanvasLib; 5 | import Thousand_Dust.canvas.PaintLib; 6 | import android.content.Context; 7 | import android.os.Looper; 8 | 9 | import Thousand_Dust.canvas.ViewLib; 10 | 11 | import luaj.Globals; 12 | import luaj.LoadState; 13 | import luaj.LuaTable; 14 | import luaj.LuaValue; 15 | import luaj.Varargs; 16 | import luaj.compiler.LuaC; 17 | import luaj.lib.TwoArgFunction; 18 | import luaj.lib.VarArgFunction; 19 | 20 | /** 21 | * @author Thousand-Dust 22 | */ 23 | public class ScriptLib extends TwoArgFunction { 24 | 25 | private Globals globals; 26 | private final String tabName = "pro"; 27 | 28 | public ScriptLib(Globals globals) { 29 | this.globals = globals; 30 | init(); 31 | } 32 | 33 | @Override 34 | public LuaValue call(LuaValue arg1, LuaValue env) { 35 | LuaTable tab = new LuaTable(); 36 | tab.set("VERSION", DevInfo.getVersion()); 37 | tab.set("UPTIME", DevInfo.getUpdateTime()); 38 | tab.set("AUTHOR", DevInfo.getAuthor()); 39 | // tab.set("killMTP", new closeMTP()); 40 | // tab.set("execCmd", new execCmd()); 41 | // tab.set("toast",new toast()); 42 | // tab.set("sleep",new sleep()); 43 | env.set(tabName, tab); 44 | //获取屏幕分辨率 45 | env.set("getWH", new GetWH()); 46 | //线程函数 47 | env.set("thread", new newThread()); 48 | return env; 49 | } 50 | 51 | private void init() { 52 | this.globals.load(this); 53 | this.globals.load(new ViewLib()); 54 | this.globals.load(new CanvasLib()); 55 | this.globals.load(new PaintLib()); 56 | this.globals.load(new BitmapLib()); 57 | LoadState.install(this.globals); 58 | LuaC.install(this.globals); 59 | } 60 | 61 | class GetWH extends VarArgFunction { 62 | @Override 63 | public Varargs invoke(Varargs args) { 64 | LuaTable table = new LuaTable(); 65 | int[] wh = Tools.getWH(Tools.getContext()); 66 | table.set("width", wh[0]); 67 | table.set("height", wh[1]); 68 | return table; 69 | } 70 | } 71 | 72 | //新线程 73 | class newThread extends VarArgFunction { 74 | @Override 75 | public Varargs invoke(final Varargs args) { 76 | new Thread(() -> args.checkfunction(1).call()).start(); 77 | return NONE; 78 | } 79 | } 80 | 81 | //关闭MTP检测 82 | class closeMTP extends VarArgFunction { 83 | @Override 84 | public Varargs invoke(final Varargs args) { 85 | try { 86 | Context appContext = Tools.getContext().createPackageContext(args.checkjstring(1), Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); 87 | String path = appContext.getFilesDir().getAbsolutePath(); 88 | String rs = args.checkboolean(2) ? "su " : "sh "; 89 | Runtime.getRuntime().exec(rs + "chmod 0000 " + path + "/tss_tmp/tssmua.zip\n exit"); 90 | Runtime.getRuntime().exec(rs + "chmod 0000 " + path + "/files/tss_tmp/\n exit"); 91 | } catch (Exception e) { 92 | return LuaValue.valueOf(e.toString()); 93 | } 94 | return LuaValue.valueOf(args.checkjstring(1) + ":MTP搜索检测已关闭"); 95 | } 96 | } 97 | 98 | 99 | 100 | //执行系统命令 101 | /*class execCmd extends VarArgFunction { 102 | boolean isClock = false; 103 | private String result = ""; 104 | private Map PermisDescrip = new ArrayMap(); 105 | private String[][] p = new String[][]{ 106 | {"rm","此命令会删除您的文件/文件夹,且无法恢复。"}, 107 | {"wget","此命令会从指定链接下载脚本,若您无法确认下载源是否安全,请不要继续执行。"}, 108 | {"curl","此命令会访问网络或下载文件,若您无法确认访问是否安全,请不要继续执行。"}, 109 | {"reboot","此命令会重启手机。"}, 110 | {"shutdown","此命令会在设定时间重启/关闭手机。"}, 111 | {"halt","此命令会直接关机。"}, 112 | {"poweroff","此命令会直接关机。"}, 113 | {":(){:|: &};:","此命令会无终止的条件递归。如果执行此操作,它将快速复制自己,从而消耗完所有的内存和CPU资源,导致冻结您的整个系统,若非特殊需求请勿继续执行!"} 114 | }; 115 | 116 | private void initPermisDescrip() 117 | { 118 | for(String[] obj:p) 119 | PermisDescrip.put(obj[0],obj[1]); 120 | } 121 | 122 | @Override 123 | public Varargs invoke(Varargs args) { 124 | initPermisDescrip(); 125 | String cmd = args.checkjstring(1); 126 | for(String[] s :p){ 127 | if(cmd.indexOf(s[0]) != -1){ 128 | showAlert(getMsg(s[0],cmd),cmd); 129 | return LuaValue.valueOf(result); 130 | } 131 | } 132 | try { 133 | return LuaValue.valueOf(Tools.execCmd(cmd, null)); 134 | } catch (Exception e) { 135 | return LuaValue.valueOf(e.getMessage()); 136 | } 137 | } 138 | 139 | public String getMsg(String name,String cmd) 140 | { 141 | String result = 142 | "脚本正在执行高危命令:" + name + 143 | "\n\n" + 144 | "执行的代码:" + 145 | cmd + 146 | "\n\n" + 147 | PermisDescrip.get(name) + 148 | "\n\n" + 149 | "是否忽略风险并执行?"; 150 | return result; 151 | } 152 | 153 | public void showAlert(final String content,final String cmd) { 154 | 155 | Runnable run = new Runnable(){ 156 | public void run() { 157 | final AlertDialog.Builder ab = new AlertDialog.Builder(Tools.getContext()); 158 | ab.setTitle("注意"); 159 | ab.setMessage(content); 160 | ab.setCancelable(false); 161 | ab.setPositiveButton("取消执行", new AlertDialog.OnClickListener(){ 162 | @Override 163 | public void onClick(DialogInterface p1, int p2) { 164 | isClock = true; 165 | result = "refuse"; 166 | ab.create().dismiss(); 167 | } 168 | }); 169 | ab.setNegativeButton("继续执行", new AlertDialog.OnClickListener(){ 170 | @Override 171 | public void onClick(DialogInterface p1, int p2) { 172 | isClock = true; 173 | try { 174 | result = Tools.execCmd(cmd, null); 175 | } catch (Exception e) { 176 | result = e.getMessage(); 177 | } 178 | } 179 | }); 180 | final AlertDialog dialog = ab.create(); 181 | if (Build.VERSION.SDK_INT >= 26) { 182 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); 183 | } else { 184 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 185 | } 186 | dialog.show(); 187 | } 188 | }; 189 | ThreadManager.runOnUiThread(run); 190 | while(isClock == false)Thread.yield(); 191 | } 192 | }*/ 193 | 194 | /*class toast extends VarArgFunction 195 | { 196 | private Toast toast = null; 197 | 198 | public void showToast(Context context, String str){ 199 | if(toast != null) { 200 | toast.cancel(); 201 | } 202 | toast = Toast.makeText(context, str, Toast.LENGTH_SHORT); 203 | toast.show(); 204 | } 205 | 206 | @Override 207 | public Varargs invoke(final Varargs args) { 208 | ThreadManager.runOnUiThread(new Runnable(){ 209 | @Override 210 | public void run(){ 211 | showToast(Tools.getContext(),args.checkjstring(1)); 212 | } 213 | }); 214 | return NONE; 215 | } 216 | }*/ 217 | 218 | 219 | /*class sleep extends VarArgFunction 220 | { 221 | @Override 222 | public Varargs invoke(Varargs args) { 223 | try { 224 | Thread.sleep(args.checkint(1)); 225 | } catch (InterruptedException e) 226 | {} 227 | return NONE; 228 | } 229 | }*/ 230 | } 231 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/Tools.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust; 2 | 3 | import android.content.Context; 4 | import android.util.DisplayMetrics; 5 | import android.widget.Toast; 6 | import java.io.File; 7 | import java.io.BufferedReader; 8 | import java.io.InputStreamReader; 9 | import java.io.Closeable; 10 | import android.ext.ThreadManager; 11 | import android.graphics.Bitmap; 12 | import android.os.StrictMode; 13 | import java.net.URL; 14 | import java.net.HttpURLConnection; 15 | import java.io.InputStream; 16 | import android.graphics.BitmapFactory; 17 | import android.os.Looper; 18 | import android.graphics.drawable.Drawable; 19 | import android.graphics.Canvas; 20 | import android.graphics.PixelFormat; 21 | 22 | public class Tools 23 | { 24 | public static Context getContext(){ 25 | return android.ext.Tools.getContext(); 26 | } 27 | 28 | public void toast(final String str) 29 | { 30 | Runnable run = new Runnable(){ 31 | @Override 32 | public void run() { 33 | Toast.makeText(getContext(),str,Toast.LENGTH_SHORT).show(); 34 | } 35 | }; 36 | ThreadManager.runOnUiThread(run); 37 | } 38 | 39 | /** 40 | * 执行系统命令, 返回执行结果 41 | * @param cmd 需要执行的命令 42 | * @param dir 执行命令的子进程的工作目录, null 表示和当前主进程工作目录相同 43 | */ 44 | public static String execCmd(String cmd, File dir) throws Exception { 45 | StringBuilder result = new StringBuilder(); 46 | 47 | Process process = null; 48 | BufferedReader bufrIn = null; 49 | BufferedReader bufrError = null; 50 | 51 | try { 52 | // 执行命令, 返回一个子进程对象(命令在子进程中执行) 53 | process = Runtime.getRuntime().exec(cmd, null, dir); 54 | 55 | // 方法阻塞, 等待命令执行完成(成功会返回0) 56 | process.waitFor(); 57 | 58 | // 获取命令执行结果, 有两个结果: 正常的输出 和 错误的输出(PS: 子进程的输出就是主进程的输入) 59 | bufrIn = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8")); 60 | bufrError = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8")); 61 | 62 | // 读取输出 63 | String line = null; 64 | while ((line = bufrIn.readLine()) != null) { 65 | result.append(line).append('\n'); 66 | } 67 | while ((line = bufrError.readLine()) != null) { 68 | result.append(line).append('\n'); 69 | } 70 | 71 | } finally { 72 | closeStream(bufrIn); 73 | closeStream(bufrError); 74 | // 销毁子进程 75 | if (process != null) { 76 | process.destroy(); 77 | } 78 | } 79 | 80 | // 返回执行结果 81 | return result.toString().substring(0,result.length()-1); 82 | } 83 | 84 | private static void closeStream(Closeable stream) { 85 | if (stream != null) { 86 | try { 87 | stream.close(); 88 | } catch (Exception e) { 89 | // nothing 90 | } 91 | } 92 | } 93 | 94 | public static boolean isMainThread() { 95 | return Looper.getMainLooper().getThread().getId() == Thread.currentThread().getId(); 96 | } 97 | 98 | public static Bitmap getHttpBitmap(String url) { 99 | if (isMainThread()) { 100 | StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 101 | StrictMode.setThreadPolicy(policy); 102 | } 103 | URL myFileURL; 104 | Bitmap bitmap=null; 105 | try { 106 | myFileURL = new URL(url); 107 | HttpURLConnection conn=(HttpURLConnection)myFileURL.openConnection(); 108 | conn.setConnectTimeout(6000); 109 | conn.setDoInput(true); 110 | conn.setUseCaches(false); 111 | conn.connect(); 112 | InputStream is = conn.getInputStream(); 113 | bitmap = BitmapFactory.decodeStream(is); 114 | is.close(); 115 | } catch (Exception e) { 116 | e.printStackTrace(); 117 | } 118 | return bitmap; 119 | } 120 | 121 | public static Bitmap drawableToBitmap(Drawable drawable) { 122 | Bitmap bitmap = Bitmap.createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), 123 | drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); 124 | Canvas canvas = new Canvas(bitmap); 125 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); 126 | drawable.draw(canvas); 127 | return bitmap; 128 | } 129 | 130 | public static int[] getWH(Context context) { 131 | DisplayMetrics dm = context.getResources().getDisplayMetrics(); 132 | return new int[]{dm.widthPixels, dm.heightPixels}; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/canvas/BitmapLib.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.canvas; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Matrix; 6 | 7 | import Thousand_Dust.luaj.LuaBitmap; 8 | import luaj.LuaNumber; 9 | import luaj.LuaTable; 10 | import luaj.LuaValue; 11 | import luaj.Varargs; 12 | import luaj.lib.TwoArgFunction; 13 | import luaj.lib.VarArgFunction; 14 | 15 | /** 16 | * @author Thousand-Dust 17 | */ 18 | public class BitmapLib extends TwoArgFunction { 19 | 20 | @Override 21 | public LuaValue call(LuaValue arg1, LuaValue env) { 22 | env.set("loadBitmap", new loadBitmap()); 23 | LuaTable table = new LuaTable(); 24 | table.set("setWidth", new setWidth()); 25 | table.set("setHeight", new setHeight()); 26 | table.set("getWH", new getWH()); 27 | table.set("remove", new remove()); 28 | 29 | if (LuaBitmap.s_metatable == null) { 30 | LuaTable mt = LuaValue.tableOf( 31 | new LuaValue[] { INDEX, table}); 32 | LuaBitmap.s_metatable = mt; 33 | } 34 | 35 | return env; 36 | } 37 | 38 | class loadBitmap extends VarArgFunction { 39 | @Override 40 | public Varargs invoke(Varargs args) { 41 | return LuaBitmap.valueOf(BitmapFactory.decodeFile(args.checkjstring(1))); 42 | } 43 | } 44 | 45 | class setWidth extends VarArgFunction { 46 | @Override 47 | public Varargs invoke(Varargs args) { 48 | Bitmap bitmap = LuaBitmap.checkbitmap(args.arg(1)); 49 | int width = bitmap.getWidth(); 50 | int height = bitmap.getHeight(); 51 | Matrix matrix = new Matrix(); 52 | matrix.postScale(width/args.tofloat(2), 1); 53 | return LuaBitmap.valueOf(Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)); 54 | } 55 | } 56 | 57 | class setHeight extends VarArgFunction { 58 | @Override 59 | public Varargs invoke(Varargs args) { 60 | Bitmap bitmap = LuaBitmap.checkbitmap(args.arg(1)); 61 | int width = bitmap.getWidth(); 62 | int height = bitmap.getHeight(); 63 | Matrix matrix = new Matrix(); 64 | matrix.postScale(1, height/args.tofloat(2)); 65 | return LuaBitmap.valueOf(Bitmap.createBitmap(bitmap, 0,0, width, height, matrix, true)); 66 | } 67 | } 68 | 69 | class getWH extends VarArgFunction { 70 | @Override 71 | public Varargs invoke(Varargs args) { 72 | Bitmap bitmap = LuaBitmap.checkbitmap(args.arg(1)); 73 | int width = bitmap.getWidth(); 74 | int height = bitmap.getHeight(); 75 | return LuaValue.tableOf(new LuaValue[]{ LuaValue.valueOf(width), LuaValue.valueOf(height) }); 76 | } 77 | } 78 | 79 | class remove extends VarArgFunction { 80 | @Override 81 | public Varargs invoke(Varargs args) { 82 | Bitmap bitmap = LuaBitmap.checkbitmap(args.arg(1)); 83 | bitmap.recycle(); 84 | return NONE; 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/canvas/CanvasLib.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.canvas; 2 | 3 | import Thousand_Dust.luaj.LuaBitmap; 4 | import Thousand_Dust.luaj.LuaCanvas; 5 | import luaj.LuaFunction; 6 | import Thousand_Dust.luaj.LuaPaint; 7 | import luaj.lib.TwoArgFunction; 8 | import luaj.LuaValue; 9 | import luaj.LuaTable; 10 | import luaj.lib.VarArgFunction; 11 | 12 | import android.graphics.Canvas; 13 | 14 | import luaj.Varargs; 15 | 16 | import android.graphics.RectF; 17 | import android.graphics.Paint; 18 | 19 | import luaj.LuaError; 20 | 21 | import android.graphics.Color; 22 | import android.util.Log; 23 | 24 | /** 25 | * @author Thousand-Dust 26 | */ 27 | public class CanvasLib extends TwoArgFunction { 28 | 29 | @Override 30 | public LuaValue call(LuaValue modname, LuaValue env) { 31 | LuaTable canvas = new LuaTable(); 32 | //绘制圆弧 33 | canvas.set("drawArc", new drawArc()); 34 | //绘制Bitmap图片 35 | canvas.set("drawBitmap", new drawBitmap()); 36 | //绘制圆 37 | canvas.set("drawCircle", new drawCircle()); 38 | //绘制背景颜色 39 | canvas.set("drawColor", new drawColor()); 40 | //绘制线段 41 | canvas.set("drawLine", new drawLine()); 42 | //绘制多条线段 43 | canvas.set("drawLines", new drawLines()); 44 | //绘制四边形 45 | canvas.set("drawRect", new drawRect()); 46 | //绘制字符串 47 | canvas.set("drawText", new drawText()); 48 | //裁剪绘制内容(四边形) 49 | canvas.set("clipRect", new clipRect()); 50 | //旋转画布 51 | canvas.set("rotate", new rotate()); 52 | //移动画布原点 53 | canvas.set("translate", new translate()); 54 | //保存画布状态 55 | canvas.set("save", new Save()); 56 | //恢复上次保存的画布状态 57 | canvas.set("restore", new Restore()); 58 | 59 | if (!env.get("package").isnil()) { 60 | env.get("package").get("loaded").set("canvas", canvas); 61 | } 62 | if (LuaCanvas.s_metatable == null) { 63 | LuaTable mt = LuaValue.tableOf( 64 | new LuaValue[] { INDEX, canvas}); 65 | LuaCanvas.s_metatable = mt; 66 | } 67 | 68 | return canvas; 69 | } 70 | 71 | class MyThread extends VarArgFunction { 72 | @Override 73 | public Varargs invoke(final Varargs args) { 74 | new Thread() { 75 | @Override 76 | public void run() { 77 | LuaFunction fun = args.checkfunction(1); 78 | try { 79 | if (args.narg() == 1) { 80 | fun.call(); 81 | } else { 82 | fun.call(args.checktable(2)); 83 | } 84 | } catch (Exception e) { 85 | throw new LuaError(e.toString()); 86 | } 87 | } 88 | }.start(); 89 | 90 | return NONE; 91 | } 92 | 93 | } 94 | 95 | class drawArc extends VarArgFunction { 96 | @Override 97 | public Varargs invoke(Varargs args) { 98 | Canvas canvas = LuaCanvas.checkcanvas(args.arg(1)); 99 | 100 | LuaTable table = args.checktable(2); 101 | RectF rectF = new RectF(table.get(1).tofloat(), table.get(2).tofloat(), table.get(3).tofloat(), table.get(4).tofloat()); 102 | 103 | canvas.drawArc(rectF, args.tofloat(3), args.tofloat(4), args.checkboolean(5), LuaPaint.checkpaint(args.arg(6))); 104 | return NONE; 105 | } 106 | } 107 | 108 | class drawBitmap extends VarArgFunction { 109 | @Override 110 | public Varargs invoke(Varargs args) { 111 | LuaCanvas.checkcanvas(args.arg(1)).drawBitmap(LuaBitmap.checkbitmap(args.arg(2)), args.tofloat(3), args.tofloat(4), LuaPaint.checkpaint(args.arg(5))); 112 | return NONE; 113 | } 114 | } 115 | 116 | class drawCircle extends VarArgFunction { 117 | @Override 118 | public Varargs invoke(Varargs args) { 119 | LuaCanvas.checkcanvas(args.arg(1)) 120 | .drawCircle(args.tofloat(2), args.tofloat(3), args.tofloat(4), LuaPaint.checkpaint(args.arg(5))); 121 | return NONE; 122 | } 123 | } 124 | 125 | class drawColor extends VarArgFunction { 126 | @Override 127 | public Varargs invoke(Varargs args) { 128 | LuaCanvas.checkcanvas(args.arg(1)).drawColor(Color.parseColor(args.tojstring(2))); 129 | return NONE; 130 | } 131 | } 132 | 133 | class drawLine extends VarArgFunction { 134 | @Override 135 | public Varargs invoke(Varargs args) { 136 | LuaCanvas.checkcanvas(args.arg(1)) 137 | .drawLine(args.tofloat(2), args.tofloat(3), args.tofloat(4), args.tofloat(5), LuaPaint.checkpaint(args.arg(6))); 138 | return NONE; 139 | } 140 | } 141 | 142 | class drawLines extends VarArgFunction { 143 | @Override 144 | public Varargs invoke(Varargs args) { 145 | LuaTable table = args.checktable(2); 146 | float[] floats = new float[table.length()]; 147 | for (int i = 0; i < floats.length; i++) { 148 | floats[i] = table.get(i).tofloat(); 149 | } 150 | LuaCanvas.checkcanvas(args.arg(1)).drawLines(floats, LuaPaint.checkpaint(args.arg(3))); 151 | return NONE; 152 | } 153 | } 154 | 155 | /*class drawProgress extends VarArgFunction { 156 | private Paint framePaint; 157 | private Paint progressPaint; 158 | 159 | public drawProgress(Paint paint) { 160 | this.framePaint = paint; 161 | progressPaint = new Paint(); 162 | progressPaint.setStyle(Paint.Style.FILL); 163 | } 164 | 165 | @Override 166 | public Varargs invoke(Varargs args) { 167 | int narg = args.narg(); 168 | if (narg >= 6) { 169 | framePaint.setColor(Color.parseColor(args.checkjstring(6))); //使用用户自定义背景颜色 170 | } else { 171 | framePaint.setColor(Color.parseColor("#FFFFFF")); 172 | //判断是否使用用户自定义进度颜色 173 | if (narg == 5) { 174 | progressPaint.setColor(Color.parseColor(args.checkjstring(5))); 175 | } else { 176 | progressPaint.setColor(Color.parseColor("#FF0000")); 177 | } 178 | } 179 | Canvas canvas = LuaCanvas.checkcanvas(args.arg(1)); //使用默认画笔 180 | //获得进度条背景矩形 181 | float left, top, right, bottom; 182 | { 183 | LuaTable table = args.checktable(2); 184 | left = table.get(1).tofloat(); 185 | top = table.get(2).tofloat(); 186 | right = table.get(3).tofloat(); 187 | bottom = table.get(4).tofloat(); 188 | } 189 | RectF frameRect = new RectF(left, top, right, bottom); 190 | //绘制进度条背景 191 | canvas.drawRect(frameRect, framePaint); 192 | //计算进度矩形 193 | float max = args.tofloat(3); 194 | float progress = args.tofloat(4); 195 | float proportion = (right - left) / max; 196 | RectF internel = new RectF(left, top, left + (progress * proportion), bottom); 197 | //绘制进度 198 | canvas.drawRect(internel, progressPaint); 199 | 200 | return NONE; 201 | } 202 | }*/ 203 | 204 | class drawRect extends VarArgFunction { 205 | @Override 206 | public Varargs invoke(Varargs args) { 207 | LuaTable table = args.checktable(2); 208 | RectF rectF = new RectF(table.get(1).tofloat(), table.get(2).tofloat(), table.get(3).tofloat(), table.get(4).tofloat()); 209 | LuaCanvas.checkcanvas(args.arg(1)).drawRect(rectF, LuaPaint.checkpaint(args.arg(3))); 210 | return NONE; 211 | } 212 | } 213 | 214 | class drawText extends VarArgFunction { 215 | @Override 216 | public Varargs invoke(Varargs args) { 217 | LuaCanvas.checkcanvas(args.arg(1)) 218 | .drawText(args.checkjstring(2), args.tofloat(3), args.tofloat(4), LuaPaint.checkpaint(args.arg(5))); 219 | return NONE; 220 | } 221 | } 222 | 223 | class clipRect extends VarArgFunction { 224 | @Override 225 | public Varargs invoke(Varargs args) { 226 | LuaTable table = args.checktable(2); 227 | LuaCanvas.checkcanvas(args.arg(1)).clipRect(new RectF(table.tofloat(1), table.tofloat(2), table.tofloat(3), table.tofloat(4))); 228 | return NONE; 229 | } 230 | } 231 | 232 | class rotate extends VarArgFunction { 233 | @Override 234 | public Varargs invoke(Varargs args) { 235 | Canvas canvas = LuaCanvas.checkcanvas(args.arg(1)); 236 | switch (args.narg()) { 237 | case 2: 238 | canvas.rotate(args.tofloat(2)); 239 | break; 240 | case 4: 241 | canvas.rotate(args.tofloat(2), args.tofloat(3), args.tofloat(4)); 242 | break; 243 | default: 244 | throw new LuaError("there is no such method: " + args); 245 | } 246 | return NONE; 247 | } 248 | } 249 | 250 | class translate extends VarArgFunction { 251 | @Override 252 | public Varargs invoke(Varargs args) { 253 | LuaCanvas.checkcanvas(args.arg(1)).translate(args.tofloat(2), args.tofloat(3)); 254 | return NONE; 255 | } 256 | } 257 | 258 | class Save extends VarArgFunction { 259 | @Override 260 | public Varargs invoke(Varargs args) { 261 | LuaCanvas.checkcanvas(args.arg(1)).save(); 262 | return NONE; 263 | } 264 | } 265 | 266 | class Restore extends VarArgFunction { 267 | @Override 268 | public Varargs invoke(Varargs args) { 269 | LuaCanvas.checkcanvas(args.arg(1)).restore(); 270 | return NONE; 271 | } 272 | } 273 | 274 | } -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/canvas/PaintLib.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.canvas; 2 | import Thousand_Dust.luaj.LuaPaint; 3 | import luaj.LuaString; 4 | import luaj.lib.TwoArgFunction; 5 | import luaj.LuaValue; 6 | import luaj.lib.VarArgFunction; 7 | import luaj.LuaTable; 8 | import luaj.Varargs; 9 | import android.graphics.Paint; 10 | import luaj.LuaError; 11 | import android.graphics.Color; 12 | 13 | /** 14 | * @author Thousand-Dust 15 | */ 16 | public class PaintLib extends TwoArgFunction { 17 | 18 | @Override 19 | public LuaValue call(LuaValue arg1, LuaValue env) { 20 | 21 | env.set("newPaint", new newPaint()); 22 | 23 | LuaTable paint = new LuaTable(); 24 | //设置画笔笔触宽 25 | paint.set("setWidth", new setWidth()); 26 | //设置画笔样式 27 | paint.set("setStyle", new setStyle()); 28 | //设置画笔颜色 29 | paint.set("setColor", new setColor()); 30 | //设置画笔画出的字符大小 31 | paint.set("setTextSize", new setTextSize()); 32 | //设置抗锯齿 33 | paint.set("setAntiAlias", new setAntiAlias()); 34 | 35 | if (!env.get("package").isnil()) { 36 | env.get("package").get("loaded").set("paint", paint); 37 | } 38 | if (LuaPaint.s_metatable == null) { 39 | LuaTable mt = LuaValue.tableOf( 40 | new LuaValue[] { INDEX, paint}); 41 | LuaPaint.s_metatable = mt; 42 | } 43 | 44 | return env; 45 | } 46 | 47 | class newPaint extends VarArgFunction { 48 | @Override 49 | public Varargs invoke(Varargs args) { 50 | return LuaPaint.valueOf(new Paint()); 51 | } 52 | } 53 | 54 | class setWidth extends VarArgFunction { 55 | @Override 56 | public Varargs invoke(Varargs args) { 57 | LuaPaint.checkpaint(args.arg(1)).setStrokeWidth(args.checkint(2)); 58 | return NONE; 59 | } 60 | } 61 | 62 | class setStyle extends VarArgFunction { 63 | @Override 64 | public Varargs invoke(Varargs args) { 65 | LuaValue value = args.checkvalue(2); 66 | 67 | Paint.Style style; 68 | if (value instanceof LuaString) { 69 | String styleStr = value.checkjstring(); 70 | switch (styleStr) { 71 | case "描边": 72 | style = Paint.Style.STROKE; 73 | break; 74 | case "填充": 75 | style = Paint.Style.FILL; 76 | break; 77 | case "描边并填充": 78 | style = Paint.Style.FILL_AND_STROKE; 79 | break; 80 | 81 | default: 82 | throw new LuaError("未知的画笔类型"); 83 | } 84 | } else { 85 | int styleNum = value.checkint(); 86 | switch (styleNum) { 87 | case 0: 88 | //描边 89 | style = Paint.Style.STROKE; 90 | break; 91 | case 1: 92 | //填充 93 | style = Paint.Style.FILL; 94 | break; 95 | case 2: 96 | //描边并填充 97 | style = Paint.Style.FILL_AND_STROKE; 98 | break; 99 | 100 | default: 101 | throw new LuaError("未知的画笔类型"); 102 | } 103 | } 104 | 105 | LuaPaint.checkpaint(args.arg(1)).setStyle(style); 106 | 107 | return NONE; 108 | } 109 | } 110 | 111 | class setColor extends VarArgFunction { 112 | @Override 113 | public Varargs invoke(Varargs args) { 114 | LuaPaint.checkpaint(args.arg(1)).setColor(Color.parseColor(args.checkjstring(2))); 115 | return NONE; 116 | } 117 | } 118 | 119 | class setTextSize extends VarArgFunction { 120 | @Override 121 | public Varargs invoke(Varargs args) { 122 | LuaPaint.checkpaint(args.arg(1)).setTextSize(args.tofloat(2)); 123 | return NONE; 124 | } 125 | } 126 | 127 | class setAntiAlias extends VarArgFunction { 128 | @Override 129 | public Varargs invoke(Varargs args) { 130 | LuaPaint.checkpaint(args.arg(1)).setAntiAlias(args.checkboolean(2)); 131 | return NONE; 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/canvas/ViewLib.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.canvas; 2 | 3 | import static Thousand_Dust.MyWindowManager.MAXIMUM_OBSCURING_OPACITY; 4 | 5 | import android.app.AlertDialog; 6 | import android.content.Intent; 7 | import android.graphics.Color; 8 | import android.os.Build; 9 | import android.os.Handler; 10 | import android.os.Looper; 11 | 12 | import Thousand_Dust.DevInfo; 13 | import Thousand_Dust.DrawView; 14 | import Thousand_Dust.MyWindowManager; 15 | import Thousand_Dust.Tools; 16 | 17 | import android.provider.Settings; 18 | import android.util.Log; 19 | import android.view.Gravity; 20 | import android.view.WindowManager; 21 | import android.widget.TextView; 22 | 23 | import luaj.Globals; 24 | import Thousand_Dust.luaj.LuaView; 25 | import luaj.LuaError; 26 | import luaj.lib.TwoArgFunction; 27 | import luaj.LuaValue; 28 | import luaj.LuaTable; 29 | import luaj.lib.VarArgFunction; 30 | import luaj.Varargs; 31 | 32 | /** 33 | * @author Thousand-Dust 34 | */ 35 | public class ViewLib extends TwoArgFunction { 36 | 37 | private Globals globals; 38 | 39 | @Override 40 | public LuaValue call(LuaValue arg1, LuaValue env) { 41 | globals = env.checkglobals(); 42 | //强制关闭绘图无障碍 43 | env.set("disDrawAcc", new disDrawAcc()); 44 | 45 | env.set("newView", new newView()); 46 | env.set("removeAllView", new removeAllView()); 47 | 48 | LuaTable view = new LuaTable(); 49 | //调用Lua绘制函数更新绘制 50 | view.set("invalidate", new invalidate()); 51 | //显示绘制 52 | view.set("show", new showDraw()); 53 | //删除绘制内容 54 | view.set("close", new closeDraw()); 55 | 56 | if (!env.get("package").isnil()) { 57 | env.get("package").get("loaded").set("view", view); 58 | } 59 | if (LuaView.s_metatable == null) { 60 | LuaTable mt = LuaValue.tableOf( 61 | new LuaValue[]{INDEX, view}); 62 | LuaView.s_metatable = mt; 63 | } 64 | 65 | return env; 66 | } 67 | 68 | class disDrawAcc extends VarArgFunction { 69 | @Override 70 | public Varargs invoke(Varargs args) { 71 | MyWindowManager.setAlpha(MAXIMUM_OBSCURING_OPACITY); 72 | return LuaValue.NONE; 73 | } 74 | } 75 | 76 | class newView extends VarArgFunction { 77 | private boolean isPrint = false; 78 | 79 | @Override 80 | public Varargs invoke(Varargs args) { 81 | if (MyWindowManager.isInstanceEmpty()) { 82 | //android版本12及以上需要开启无障碍 83 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && MyWindowManager.getAlpha() > MAXIMUM_OBSCURING_OPACITY) { 84 | showPermissionAlert(); 85 | } else { 86 | showOrdinaryAlert(); 87 | } 88 | } 89 | DrawView drawView = new DrawView(Tools.getContext(), globals); 90 | MyWindowManager.getInstance().addView(drawView); 91 | return LuaView.valueOf(drawView); 92 | } 93 | 94 | public void showOrdinaryAlert() { 95 | final boolean[] result = {false, false}; 96 | Runnable run = () -> { 97 | //复制函数开发者信息可点击文字 98 | TextView devText = new TextView(Tools.getContext()); 99 | devText.setText("输出并复制函数开发者信息"); 100 | devText.setTextColor(Color.parseColor("#00FFFF")); 101 | devText.setGravity(Gravity.CENTER_HORIZONTAL); 102 | devText.setPadding(0, 20, 0, 0); 103 | devText.setOnClickListener((v) -> { 104 | android.ext.Tools.copyText(DevInfo.getAuthor()); 105 | if (!isPrint) { 106 | globals.STDOUT.println(DevInfo.getAuthor()); 107 | isPrint = true; 108 | } 109 | }); 110 | 111 | //绘制提示弹窗 112 | final AlertDialog.Builder ab = new AlertDialog.Builder(Tools.getContext()); 113 | ab.setTitle("绘制"); 114 | ab.setMessage("脚本即将在屏幕上绘图\n同意继续,拒绝则退出脚本。"); 115 | ab.setView(devText); 116 | ab.setCancelable(false); 117 | ab.setPositiveButton("同意", (p1, p2) -> { 118 | MyWindowManager.newInstance(Tools.getContext()); 119 | result[1] = true; 120 | }); 121 | ab.setNegativeButton("拒绝", (p1, p2) -> { 122 | result[1] = false; 123 | }); 124 | ab.setOnDismissListener((dialogInterface) -> result[0] = true); 125 | final AlertDialog dialog = ab.create(); 126 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 127 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); 128 | } else { 129 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 130 | } 131 | dialog.show(); 132 | }; 133 | 134 | new Handler(Looper.getMainLooper()).post(run); 135 | while (!result[0]) { 136 | Thread.yield(); 137 | } 138 | //拒绝在屏幕上绘制 139 | if (!result[1]) { 140 | throw new LuaError("用户拒绝在屏幕上绘制"); 141 | } 142 | } 143 | 144 | public void showPermissionAlert() { 145 | final boolean[] isClock = {false}; 146 | Runnable run = () -> { 147 | //复制函数开发者信息可点击文字 148 | TextView devText = new TextView(Tools.getContext()); 149 | devText.setText("输出并复制函数开发者信息"); 150 | devText.setTextColor(Color.parseColor("#00FFFF")); 151 | devText.setGravity(Gravity.CENTER_HORIZONTAL); 152 | devText.setPadding(0, 20, 0, 0); 153 | devText.setOnClickListener((v) -> { 154 | android.ext.Tools.copyText(DevInfo.getAuthor()); 155 | if (!isPrint) { 156 | globals.STDOUT.println(DevInfo.getAuthor()); 157 | isPrint = true; 158 | } 159 | }); 160 | 161 | //权限请求弹窗 162 | final AlertDialog.Builder ab = new AlertDialog.Builder(Tools.getContext()); 163 | ab.setTitle("权限请求"); 164 | ab.setMessage("脚本即将在屏幕上绘图\n" + 165 | "但因为您的Android设备版本为12或以上,需要开启无障碍(或调用函数\"disDrawAcc()\")\n" + 166 | "同意跳转权限页面,拒绝结束脚本。"); 167 | ab.setView(devText); 168 | ab.setCancelable(false); 169 | ab.setPositiveButton("同意", (p1, p2) -> { 170 | Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); 171 | Tools.getContext().startActivity(intent); 172 | }); 173 | ab.setNegativeButton("拒绝", null); 174 | ab.setOnDismissListener((dialogInterface) -> isClock[0] = true); 175 | final AlertDialog dialog = ab.create(); 176 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 177 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); 178 | } else { 179 | dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 180 | } 181 | dialog.show(); 182 | }; 183 | 184 | new Handler(Looper.getMainLooper()).post(run); 185 | while (!isClock[0]) { 186 | Thread.yield(); 187 | } 188 | } 189 | } 190 | 191 | class invalidate extends VarArgFunction { 192 | @Override 193 | public Varargs invoke(Varargs args) { 194 | LuaView.checkview(args.arg(1)).postInvalidate(); 195 | return NONE; 196 | } 197 | } 198 | 199 | class showDraw extends VarArgFunction { 200 | @Override 201 | public Varargs invoke(Varargs varargs) { 202 | DrawView luaView = LuaView.checkview(varargs.arg(1)); 203 | luaView.setDrawFun(varargs.checkfunction(2)); 204 | luaView.start(varargs.optint(3, 60)); 205 | return LuaValue.NONE; 206 | } 207 | } 208 | 209 | class closeDraw extends VarArgFunction { 210 | @Override 211 | public Varargs invoke(Varargs varargs) { 212 | DrawView luaView = LuaView.checkview(varargs.arg(1)); 213 | MyWindowManager.getInstance().removeView(luaView); 214 | return LuaValue.NONE; 215 | } 216 | } 217 | 218 | private class removeAllView extends VarArgFunction { 219 | @Override 220 | public Varargs invoke(Varargs varargs) { 221 | MyWindowManager.getInstance().removeAllViews(); 222 | return LuaValue.NONE; 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/luaj/LuaBitmap.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.luaj; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import luaj.LuaValue; 6 | 7 | /** 8 | * @author Thousand-Dust 9 | */ 10 | public class LuaBitmap extends LuaValue { 11 | 12 | private Bitmap bitmap; 13 | public static LuaValue s_metatable; 14 | 15 | @Override 16 | public int type() { 17 | return 11; 18 | } 19 | 20 | @Override 21 | public String typename() { 22 | return "bitmap"; 23 | } 24 | 25 | @Override 26 | public LuaValue getmetatable() { 27 | return s_metatable; 28 | } 29 | 30 | public static LuaBitmap valueOf(Bitmap bitmap){ 31 | return new LuaBitmap(bitmap); 32 | } 33 | 34 | private LuaBitmap(Bitmap bitmap){ 35 | this.bitmap = bitmap; 36 | } 37 | 38 | public static Bitmap checkbitmap(LuaValue luaValue) { 39 | return luaValue instanceof LuaBitmap ? ((LuaBitmap) luaValue).bitmap : null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/luaj/LuaCanvas.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.luaj; 2 | import android.graphics.Canvas; 3 | 4 | import luaj.LuaValue; 5 | 6 | /** 7 | * @author Thousand-Dust 8 | */ 9 | public class LuaCanvas extends LuaValue { 10 | 11 | private Canvas canvas; 12 | public static LuaValue s_metatable; 13 | 14 | @Override 15 | public int type() { 16 | return 12; 17 | } 18 | 19 | @Override 20 | public String typename() { 21 | return "canvas"; 22 | } 23 | 24 | @Override 25 | public LuaValue getmetatable() { 26 | return s_metatable; 27 | } 28 | 29 | public static LuaCanvas valueOf(Canvas canvas){ 30 | return new LuaCanvas(canvas); 31 | } 32 | 33 | private LuaCanvas(Canvas canvas){ 34 | this.canvas = canvas; 35 | } 36 | 37 | public static Canvas checkcanvas(LuaValue luaValue) { 38 | return luaValue instanceof LuaCanvas ? ((LuaCanvas) luaValue).canvas : null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/luaj/LuaPaint.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.luaj; 2 | import android.graphics.Paint; 3 | 4 | import luaj.LuaValue; 5 | 6 | /** 7 | * @author Thousand-Dust 8 | */ 9 | public class LuaPaint extends LuaValue { 10 | 11 | private Paint paint; 12 | public static LuaValue s_metatable; 13 | 14 | @Override 15 | public int type() { 16 | return 13; 17 | } 18 | 19 | @Override 20 | public String typename() { 21 | return "paint"; 22 | } 23 | 24 | @Override 25 | public LuaValue getmetatable() { 26 | return s_metatable; 27 | } 28 | 29 | public static LuaPaint valueOf(Paint paint){ 30 | return new LuaPaint(paint); 31 | } 32 | 33 | private LuaPaint(Paint paint){ 34 | this.paint = paint; 35 | } 36 | 37 | public static Paint checkpaint(LuaValue luaValue) { 38 | return luaValue instanceof LuaPaint ? ((LuaPaint) luaValue).paint : null; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/luaj/LuaView.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.luaj; 2 | 3 | import Thousand_Dust.DrawView; 4 | 5 | import luaj.LuaValue; 6 | 7 | /** 8 | * @author Thousand-Dust 9 | */ 10 | public class LuaView extends LuaValue { 11 | 12 | private DrawView view; 13 | public static LuaValue s_metatable; 14 | 15 | @Override 16 | public int type() { 17 | return 10; 18 | } 19 | 20 | @Override 21 | public String typename() { 22 | return "view"; 23 | } 24 | 25 | @Override 26 | public LuaValue getmetatable() { 27 | return s_metatable; 28 | } 29 | 30 | public static LuaView valueOf(DrawView v){ 31 | return new LuaView(v); 32 | } 33 | 34 | private LuaView(DrawView view){ 35 | this.view = view; 36 | } 37 | 38 | public static DrawView checkview(LuaValue luaValue) { 39 | return luaValue instanceof LuaView ? ((LuaView) luaValue).view : null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/socket/LuaServerSocket.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.socket; 2 | 3 | import android.os.Handler; 4 | import android.os.Message; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import luaj.LuaString; 9 | import luaj.LuaTable; 10 | import luaj.LuaValue; 11 | import luaj.Varargs; 12 | import luaj.lib.TwoArgFunction; 13 | import luaj.lib.VarArgFunction; 14 | 15 | import java.io.ByteArrayOutputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.net.ServerSocket; 19 | import java.net.Socket; 20 | 21 | public class LuaServerSocket extends TwoArgFunction { 22 | 23 | private interface SocketEvent { 24 | void socketEvent(LuaString luaStr); 25 | } 26 | 27 | @Override 28 | public LuaValue call(LuaValue arg1, LuaValue arg2) { 29 | LuaTable t = new LuaTable(); 30 | t.set("setSocketEvent", new setSocketEvent()); 31 | arg2.set("SeverSocket", t); 32 | 33 | return t; 34 | } 35 | 36 | class setSocketEvent extends VarArgFunction { 37 | 38 | private ServerSocket ss; 39 | private Socket socket; 40 | private SocketEvent event; 41 | 42 | private Handler handler = new Handler() { 43 | @Override 44 | public void handleMessage(@NonNull Message msg) { 45 | switch (msg.what) { 46 | case 0x001: 47 | //向lua发送接收到的Socket消息内容 48 | event.socketEvent((LuaString)msg.obj); 49 | break; 50 | } 51 | } 52 | }; 53 | 54 | @Override 55 | public Varargs invoke(final Varargs args) { 56 | new Thread() { 57 | @Override 58 | public void run() { 59 | InputStream in = null; 60 | ByteArrayOutputStream out = null; 61 | while (true) { 62 | try { 63 | ss = new ServerSocket(args.checkint(1)); 64 | socket = ss.accept(); 65 | in = socket.getInputStream(); 66 | out = new ByteArrayOutputStream(); 67 | byte[] bytes = new byte[1024]; 68 | int len = -1; 69 | while ((len = in.read(bytes)) != -1) { 70 | out.write(bytes, 0, len); 71 | } 72 | 73 | //发送消息,让lua线程向lua发送接收到的Socket消息内容 74 | Message message = new Message(); 75 | message.what = 0x001; 76 | message.obj = LuaString.valueOf(out.toByteArray()); 77 | handler.sendMessage(message); 78 | } catch (IOException e) { 79 | continue; 80 | } finally { 81 | try { 82 | if (in != null) 83 | in.close(); 84 | if (out != null) 85 | out.close(); 86 | } catch (IOException e) { 87 | } 88 | } 89 | } 90 | 91 | } 92 | }.start(); 93 | 94 | event = new SocketEvent() { 95 | @Override 96 | public void socketEvent(LuaString luaStr) { 97 | args.checkfunction(2).call(luaStr); 98 | } 99 | }; 100 | 101 | return NONE; 102 | } 103 | 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/Thousand_Dust/socket/LuaSocket.java: -------------------------------------------------------------------------------- 1 | package Thousand_Dust.socket; 2 | 3 | import luaj.LuaError; 4 | import luaj.LuaString; 5 | import luaj.LuaTable; 6 | import luaj.LuaValue; 7 | import luaj.Varargs; 8 | import luaj.lib.TwoArgFunction; 9 | import luaj.lib.VarArgFunction; 10 | 11 | import java.io.IOException; 12 | import java.io.OutputStream; 13 | import java.net.Socket; 14 | 15 | public class LuaSocket extends TwoArgFunction { 16 | 17 | @Override 18 | public LuaValue call(LuaValue arg1, LuaValue arg2) { 19 | LuaTable t = new LuaTable(); 20 | t.set("new", new newSocket()); 21 | arg2.set("Socket", t); 22 | 23 | return t; 24 | } 25 | 26 | class mSocket { 27 | 28 | private Socket socket; 29 | 30 | public Varargs get(Varargs arg) { 31 | try { 32 | socket = new Socket(arg.checkjstring(1), arg.checkint(2)); 33 | } catch (IOException e) { 34 | throw new LuaError("来自Socket的错误:"+e.toString()); 35 | } 36 | 37 | LuaTable t = new LuaTable(); 38 | t.set("write", new Write()); 39 | 40 | return t; 41 | } 42 | 43 | class Write extends VarArgFunction { 44 | @Override 45 | public Varargs invoke(Varargs args) { 46 | LuaString content = args.checkstring(1); 47 | OutputStream out = null; 48 | try { 49 | out = socket.getOutputStream(); 50 | out.write(content.m_bytes, content.m_offset, content.m_length); 51 | out.flush(); 52 | } catch (IOException e) { 53 | throw new LuaError("来自Socket.write:"+e.toString()); 54 | } finally { 55 | try { 56 | if (out != null) 57 | out.close(); 58 | } catch (IOException e) { 59 | } 60 | } 61 | 62 | return NONE; 63 | } 64 | } 65 | 66 | } 67 | 68 | class newSocket extends VarArgFunction { 69 | @Override 70 | public Varargs invoke(Varargs arg) { 71 | return new mSocket().get(arg); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/gg/function/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gg.function; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends Activity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | } 12 | } -------------------------------------------------------------------------------- /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/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/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/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 | GG-CustomizeFunction 3 | 用于创建可穿透事件悬浮窗,android版本12及以上才需要开启 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/xml/accessibility_config.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.application' version '7.2.1' apply false 4 | id 'com.android.library' version '7.2.1' apply false 5 | } 6 | 7 | task clean(type: Delete) { 8 | delete rootProject.buildDir 9 | } -------------------------------------------------------------------------------- /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 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnahz77/GG-CustomizeFunction/0419d92aab270e562459c85fa90002cce5620d22/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Sep 25 21:54:28 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-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 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "GG-CustomizeFunction" 16 | include ':app' 17 | --------------------------------------------------------------------------------