整理代码并更新依赖版本

This commit is contained in:
2021-11-27 18:59:44 +08:00
parent 14d1b9c5ac
commit 5d82e9a104
13 changed files with 135 additions and 97 deletions

3
.idea/gradle.xml generated
View File

@@ -4,9 +4,10 @@
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="PLATFORM" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="11" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@@ -26,5 +26,20 @@
<option name="name" value="Google" /> <option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" /> <option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="maven3" />
<option name="name" value="maven3" />
<option name="url" value="https://www.jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://maven.aliyun.com/nexus/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://maven.aliyun.com/nexus/content/repositories/jcenter" />
</remote-repository>
</component> </component>
</project> </project>

2
.idea/misc.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

View File

@@ -1,7 +1,44 @@
# TSBattery # TSBattery
![Eclipse Marketplace](https://img.shields.io/badge/build-passing-brightgreen)
![Eclipse Marketplace](https://img.shields.io/badge/license-GPL3.0-blue)
![Eclipse Marketplace](https://img.shields.io/badge/version-v2.4-green)
<br/><br/>
TSBattery a new way to save your battery avoid cancer apps hacker it.<br/> TSBattery a new way to save your battery avoid cancer apps hacker it.<br/>
TSBattery 是一个旨在使 QQ、TIM 变得更省电的开源 Xposed 模块 TSBattery 是一个旨在使 QQ、TIM 变得更省电的开源 Xposed 模块
# Get startted # 开始使用
此模块支持原生 Xposed、Lsposed(作用域 QQ、TIM 如果不起作用勾选系统框架)、EdXposed(不推荐)、太极无极(阴和阳)、Pine(梦境模块) 点击下载最新版本
<a href='https://github.com/fankes/TSBattery/releases'>![Eclipse Marketplace](https://img.shields.io/badge/download-v2.4-green)</a>
<br/><br/>
⚠️适配说明:此模块支持原生 Xposed、Lsposed(作用域 QQ、TIM 如果不起作用勾选系统框架)、EdXposed(不推荐)、太极无极(阴和阳)、Pine(梦境模块)
# 禁止任何商业用途 # 禁止任何商业用途
本模块完全开源免费,如果好用你可以打赏支持开发,严禁未经许可进行二改贩卖,违者必惩必究。 本模块完全开源免费,如果好用你可以打赏支持开发,严禁未经许可进行二改贩卖,违者必惩必究。
# 开始贡献
欢迎为此项目进行新版本的适配代码贡献!<br/>
## 代码规范:
### 1.全部提交代码必须使用 IDE(Android Studio 或 IDEA) 进行格式化,未经格式化的代码将拒绝合并提交请求
### 2.代码必须使用 4 spaces 缩进格式化
### 3.代码注释规范:
1.第一种注释方式:可使用在方法名或顶级变量名上
```kotlin
/** 注释内容 */
fun a() {
}
/**
* 注释名称
* @param test 方法名称
* @return 返回值名称
*/
fun a(test: String) {
}
```
2.第二种注释方式:仅可使用在变量后方
```kotlin
val a = "" // 变量注释
```
⚠️注意:只允许两个 // 后方要有空格
### 4.调试性质或大批量注释代码,禁止提交
### 5.类名和方法名仅能由开发者进行修改和提交,禁止随意修改项目名称、方法名称以及类名
### 6.禁止随意更新项目依赖以及增加新的依赖,有问题请提前提交到 issues 进行说明
### 7.禁止更新项目版本号,版本号交由开发者合并代码并发布 release 版本
### 8.代码语言要求,请统一使用 Kotlin除特殊情况外不接受其他语言的提交

View File

@@ -20,10 +20,10 @@ android {
defaultConfig { defaultConfig {
applicationId "com.fankes.tsbattery" applicationId "com.fankes.tsbattery"
minSdkVersion 22 minSdkVersion 22
//noinspection ExpiredTargetSdkVersion,OldTargetApi //noinspection ExpiredTargetSdkVersion
targetSdkVersion 26 targetSdkVersion 28
versionCode 6 versionCode 7
versionName "2.3" versionName "2.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -46,25 +46,18 @@ android {
dependencies { dependencies {
compileOnly 'de.robv.android.xposed:api:82' compileOnly 'de.robv.android.xposed:api:82'
// 基础依赖包,必须要依赖 // 基础依赖包
implementation 'com.gyf.immersionbar:immersionbar:3.0.0' implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
// fragment快速实现(可选) // Fragment 快速实现
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0' implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0'
// kotlin扩展(可选) // Kotlin 扩展
implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0' implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0'
//noinspection GradleDependency,DifferentStdlibGradleVersion
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
//noinspection GradleDependency implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.core:core-ktx:1.5.0' implementation 'androidx.appcompat:appcompat:1.4.0'
//noinspection GradleDependency implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
//noinspection GradleDependency
implementation 'com.google.android.material:material:1.3.0'
//noinspection GradleDependency
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
//noinspection GradleDependency androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//noinspection GradleDependency
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
} }

View File

@@ -29,8 +29,10 @@
android:value="82" /> android:value="82" />
<activity <activity
android:name="com.fankes.tsbattery.MainActivity" android:name="com.fankes.tsbattery.ui.MainActivity"
android:exported="true"
android:label="@string/app_name"> android:label="@string/app_name">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" /> <category android:name="de.robv.android.xposed.category.MODULE_SETTINGS" />
@@ -40,8 +42,10 @@
<activity-alias <activity-alias
android:name="com.fankes.tsbattery.Home" android:name="com.fankes.tsbattery.Home"
android:enabled="true" android:enabled="true"
android:exported="true"
android:label="@string/app_name" android:label="@string/app_name"
android:targetActivity="com.fankes.tsbattery.MainActivity"> android:targetActivity="com.fankes.tsbattery.ui.MainActivity">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />

View File

@@ -27,7 +27,6 @@ import android.app.AlertDialog
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.widget.Toast
import androidx.annotation.Keep import androidx.annotation.Keep
import com.fankes.tsbattery.utils.XPrefUtils import com.fankes.tsbattery.utils.XPrefUtils
import de.robv.android.xposed.* import de.robv.android.xposed.*
@@ -37,6 +36,11 @@ import java.util.*
@Keep @Keep
class HookMain : IXposedHookLoadPackage { class HookMain : IXposedHookLoadPackage {
companion object {
private const val BASE_CHAT_PIE = "activity.aio.core.BaseChatPie"
}
/** 仅作用于替换的 Hook 方法体 */ /** 仅作用于替换的 Hook 方法体 */
private val replaceToNull = object : XC_MethodReplacement() { private val replaceToNull = object : XC_MethodReplacement() {
override fun replaceHookedMethod(param: MethodHookParam?): Any? { override fun replaceHookedMethod(param: MethodHookParam?): Any? {
@@ -65,37 +69,51 @@ class HookMain : IXposedHookLoadPackage {
) )
} }
/**
* 忽略异常运行
* @param it 正常回调
*/
private fun runWithoutError(error: String, it: () -> Unit) {
try {
it()
} catch (e: Error) {
logE("hookFailed: $error", e)
} catch (e: Exception) {
logE("hookFailed: $error", e)
} catch (e: Throwable) {
logE("hookFailed: $error", e)
}
}
/** /**
* 这个类 BaseChatPie 是控制聊天界面的 * 这个类 BaseChatPie 是控制聊天界面的
* 里面有两个随机混淆的方法 * 里面有两个随机混淆的方法 ⬇️
* remainScreenOn、cancelRemainScreenOn
* 这两个方法一个是挂起电源锁常驻亮屏 * 这两个方法一个是挂起电源锁常驻亮屏
* 一个是停止常驻亮屏 * 一个是停止常驻亮屏
* 不由分说每个版本混淆的方法名都会变 * 不由分说每个版本混淆的方法名都会变
* 所以说每个版本重新适配 - 也可以提交分支帮我适配 * 所以说每个版本重新适配 - 也可以提交分支帮我适配
* 8.8.17 版本是 bd be
* 8.8.23 版本是 bf bg
* 8.8.38 版本是 bi bj
* ⚠️ Hook 错了方法会造成闪退! * ⚠️ Hook 错了方法会造成闪退!
* @param version QQ 版本 * @param version QQ 版本
*/ */
private fun XC_LoadPackage.LoadPackageParam.hookBaseChatPie(version: String) { private fun XC_LoadPackage.LoadPackageParam.hookBaseChatPie(version: String) {
when (version) { when (version) {
"8.8.17" -> { "8.8.17" -> {
replaceToNull("activity.aio.core.BaseChatPie", "bd") replaceToNull(BASE_CHAT_PIE, "bd")
replaceToNull("activity.aio.core.BaseChatPie", "be") replaceToNull(BASE_CHAT_PIE, "be")
} }
"8.8.23" -> { "8.8.23" -> {
replaceToNull("activity.aio.core.BaseChatPie", "bf") replaceToNull(BASE_CHAT_PIE, "bf")
replaceToNull("activity.aio.core.BaseChatPie", "bg") replaceToNull(BASE_CHAT_PIE, "bg")
} }
"8.8.38" -> { "8.8.38" -> {
replaceToNull("activity.aio.core.BaseChatPie", "bi") replaceToNull(BASE_CHAT_PIE, "bi")
replaceToNull("activity.aio.core.BaseChatPie", "bj") replaceToNull(BASE_CHAT_PIE, "bj")
} }
// JiZhi适配 /** 贡献者JiZhi-Error */
"8.8.50" -> { "8.8.50" -> {
replaceToNull("activity.aio.core.BaseChatPie", "bj")//remainScreenOn replaceToNull(BASE_CHAT_PIE, "bj")
replaceToNull("activity.aio.core.BaseChatPie", "bk")//cancelRemainScreenOn replaceToNull(BASE_CHAT_PIE, "bk")
} }
else -> logD("$version not supported!") else -> logD("$version not supported!")
} }
@@ -132,17 +150,15 @@ class HookMain : IXposedHookLoadPackage {
) )
/** 经过测试 QQ 与 TIM 这两个是一个模子里面的东西,所以他们的类名也基本上是一样的 */ /** 经过测试 QQ 与 TIM 这两个是一个模子里面的东西,所以他们的类名也基本上是一样的 */
"com.tencent.mobileqq", "com.tencent.tim" -> { "com.tencent.mobileqq", "com.tencent.tim" -> {
try { runWithoutError("wakeLock acquire()") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock", "android.os.PowerManager\$WakeLock",
lpparam.classLoader, lpparam.classLoader,
"acquire", "acquire",
replaceToNull replaceToNull
) )
} catch (e: Throwable) {
logE("handleLoadPackage: hook wakeLock acquire() Failed", e)
} }
try { runWithoutError("hook wakeLock acquire(time)") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock", "android.os.PowerManager\$WakeLock",
lpparam.classLoader, lpparam.classLoader,
@@ -150,11 +166,9 @@ class HookMain : IXposedHookLoadPackage {
Long::class.java, Long::class.java,
replaceToNull replaceToNull
) )
} catch (e: Throwable) {
logE("handleLoadPackage: hook wakeLock acquire(time) Failed", e)
} }
/** 增加通知栏文本显示守护状态 */ /** 增加通知栏文本显示守护状态 */
try { runWithoutError("Notification") {
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
"android.app.Notification\$Builder", "android.app.Notification\$Builder",
lpparam.classLoader, lpparam.classLoader,
@@ -170,12 +184,10 @@ class HookMain : IXposedHookLoadPackage {
} }
} }
}) })
} catch (e: Throwable) {
logE("handleLoadPackage: hook Notification Failed", e)
} }
/** 判断是否开启提示模块运行信息 */ /** 判断是否开启提示模块运行信息 */
if (XPrefUtils.getBoolean(HookMedium.ENABLE_RUN_INFO)) if (XPrefUtils.getBoolean(HookMedium.ENABLE_RUN_INFO))
try { runWithoutError("SplashActivity") {
/** /**
* Hook 启动界面的第一个 [Activity] * Hook 启动界面的第一个 [Activity]
* QQ 和 TIM 都是一样的类 * QQ 和 TIM 都是一样的类
@@ -190,7 +202,7 @@ class HookMain : IXposedHookLoadPackage {
override fun afterHookedMethod(param: MethodHookParam?) { override fun afterHookedMethod(param: MethodHookParam?) {
val self = param?.thisObject as? Activity ?: return val self = param?.thisObject as? Activity ?: return
try { runWithoutError("模块已激活,但显示信息弹窗失败了") {
AlertDialog.Builder( AlertDialog.Builder(
self, self,
android.R.style.Theme_Material_Light_Dialog android.R.style.Theme_Material_Light_Dialog
@@ -217,21 +229,13 @@ class HookMain : IXposedHookLoadPackage {
) )
.setPositiveButton("我知道了", null) .setPositiveButton("我知道了", null)
.show() .show()
} catch (e: Exception) {
Toast.makeText(
self,
"模块已激活,但显示信息弹窗失败了\n$e",
Toast.LENGTH_SHORT
).show()
} }
} }
}) })
} catch (e: Exception) {
logE("handleLoadPackage: hook SplashActivity Failed", e)
} }
/** 关闭保守模式后不再仅仅作用于系统电源锁 */ /** 关闭保守模式后不再仅仅作用于系统电源锁 */
if (!XPrefUtils.getBoolean(HookMedium.ENABLE_WHITE_MODE)) { if (!XPrefUtils.getBoolean(HookMedium.ENABLE_WHITE_MODE)) {
try { runWithoutError("BaseChatPie(first time)") {
/** 通过在 SplashActivity 里取到应用的版本号 */ /** 通过在 SplashActivity 里取到应用的版本号 */
XposedHelpers.findAndHookMethod( XposedHelpers.findAndHookMethod(
"com.tencent.mobileqq.activity.SplashActivity", "com.tencent.mobileqq.activity.SplashActivity",
@@ -246,18 +250,14 @@ class HookMain : IXposedHookLoadPackage {
val version = val version =
self.packageManager.getPackageInfo(name, 0).versionName self.packageManager.getPackageInfo(name, 0).versionName
/** 这个地方我们只处理 QQ */ /** 这个地方我们只处理 QQ */
try { runWithoutError("BaseChatPie") {
if (name == "com.tencent.mobileqq") if (name == "com.tencent.mobileqq")
lpparam.hookBaseChatPie(version) lpparam.hookBaseChatPie(version)
} catch (e: Exception) {
logE("handleLoadPackage: hook BaseChatPie Failed", e)
} }
} }
}) })
} catch (e: Exception) {
logE("handleLoadPackage: hook BaseChatPie(first time) Failed", e)
} }
try { runWithoutError("WakerLock") {
/** /**
* 一个不知道是什么作用的电源锁 * 一个不知道是什么作用的电源锁
* 同样直接干掉 * 同样直接干掉
@@ -268,10 +268,8 @@ class HookMain : IXposedHookLoadPackage {
"lock", Long::class.java, "lock", Long::class.java,
replaceToNull replaceToNull
) )
} catch (e: Exception) {
logE("handleLoadPackage: hook WakerLock Failed", e)
} }
try { runWithoutError("QQLSActivity") {
/** /**
* Hook 掉一个一像素保活 [Activity] 真的我怎么都想不到讯哥的程序员做出这种事情 * Hook 掉一个一像素保活 [Activity] 真的我怎么都想不到讯哥的程序员做出这种事情
* 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电 * 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电
@@ -317,10 +315,8 @@ class HookMain : IXposedHookLoadPackage {
"run", "run",
replaceToNull replaceToNull
) )
} catch (e: Exception) {
logE("handleLoadPackage: hook QQLSActivity Failed", e)
} }
try { runWithoutError("WakerLockMonitor") {
/** /**
* 这个是毒瘤核心类 * 这个是毒瘤核心类
* WakeLockMonitor * WakeLockMonitor
@@ -394,10 +390,8 @@ class HookMain : IXposedHookLoadPackage {
XposedBridge.hookMethod(onProcessBG5Min, replaceToNull) XposedBridge.hookMethod(onProcessBG5Min, replaceToNull)
XposedBridge.hookMethod(writeReport, replaceToNull) XposedBridge.hookMethod(writeReport, replaceToNull)
} }
} catch (e: Throwable) {
logE("handleLoadPackage: hook WakerLockMonitor Failed", e)
} }
logD("handleLoadPackage: hook Complete!") logD("hook Completed!")
} }
} }
} }

View File

@@ -26,7 +26,7 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.annotation.Keep import androidx.annotation.Keep
import com.fankes.tsbattery.MainActivity import com.fankes.tsbattery.ui.MainActivity
@Keep @Keep
object HookMedium { object HookMedium {

View File

@@ -23,7 +23,7 @@
"LocalVariableName", "SameParameterValue" "LocalVariableName", "SameParameterValue"
) )
package com.fankes.tsbattery package com.fankes.tsbattery.ui
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
@@ -40,6 +40,8 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.SwitchCompat
import androidx.constraintlayout.utils.widget.ImageFilterView import androidx.constraintlayout.utils.widget.ImageFilterView
import com.fankes.tsbattery.BuildConfig
import com.fankes.tsbattery.R
import com.fankes.tsbattery.hook.HookMedium import com.fankes.tsbattery.hook.HookMedium
import com.fankes.tsbattery.utils.FileUtils import com.fankes.tsbattery.utils.FileUtils
import com.gyf.immersionbar.ImmersionBar import com.gyf.immersionbar.ImmersionBar

View File

@@ -4,7 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
tools:context=".MainActivity" tools:context=".ui.MainActivity"
tools:ignore="HardcodedText"> tools:ignore="HardcodedText">
<LinearLayout <LinearLayout

View File

@@ -1,15 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = "1.4.20" ext.kotlin_version = "1.6.0"
repositories { repositories {
google() google()
//noinspection JcenterRepositoryObsolete maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
jcenter() maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url "https://www.jitpack.io" }
mavenCentral()
} }
dependencies { dependencies {
//noinspection AndroidGradlePluginVersion classpath "com.android.tools.build:gradle:7.0.3"
classpath "com.android.tools.build:gradle:4.1.1"
//noinspection DifferentKotlinGradleVersion
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
@@ -20,8 +20,10 @@ buildscript {
allprojects { allprojects {
repositories { repositories {
google() google()
//noinspection JcenterRepositoryObsolete maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
jcenter() maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
maven { url "https://www.jitpack.io" }
mavenCentral()
} }
} }

View File

@@ -1,6 +1,6 @@
#Sat Sep 04 04:05:23 CST 2021 #Sat Sep 04 04:05:23 CST 2021
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME