Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
3c30c532a4
|
|||
8f7772d047
|
|||
c148a535c8
|
|||
a5448a2c61
|
|||
a8a01e8afa
|
|||
c322c3dc29
|
|||
2e9761f01a
|
|||
0fd1a33533
|
|||
e465739f95
|
|||
52f992a6cd
|
|||
37be07f11d
|
|||
d8d9fc8c41
|
|||
f27fdb2f25
|
|||
3629ca3df5
|
|||
12a1c12f8a
|
|||
bc41ac2bdc
|
|||
5f13e203f0
|
|||
69a68999a5
|
|||
bc48d59b59
|
|||
cadf7b8873
|
|||
7f0c8dd2b5
|
|||
67349c45fd
|
|||
4ab612d5fa
|
|||
bb4b942dae
|
|||
ff0931b7bc
|
|||
fc42a0ddf0
|
|||
abab096ae0
|
|||
ce8e786b5b
|
|||
dd6c69b337
|
|||
69564cccf6
|
|||
a8c16d7823
|
|||
3616919978
|
|||
c5dfbcbe0d
|
|||
f21e8769e0
|
|||
eada17db44
|
|||
67209859c4
|
|||
a65b3c1dbe
|
|||
6375aa7844
|
|||
cbd6fd038d
|
|||
7fcf9228f4
|
|||
d995c69b5c
|
|||
376a2a5890
|
|||
e2ff60e2ef
|
|||
ad0b6d253a
|
|||
76af063ed8
|
|||
e0fdf269a0
|
|||
b1d4cd4017
|
63
.github/workflows/commit_ci.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Automatic Build on Commit
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**.txt'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build CI
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup cmake
|
||||
uses: jwlawson/actions-setup-cmake@v1
|
||||
with:
|
||||
cmake-version: '3.22.1'
|
||||
- name: Prepare Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-package: jdk
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
- name: Cache Gradle Dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
!~/.gradle/caches/build-cache-*
|
||||
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
|
||||
restore-keys: |
|
||||
gradle-deps
|
||||
- name: Cache Gradle Build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches/build-cache-*
|
||||
key: gradle-builds-core-${{ github.sha }}
|
||||
restore-keys: |
|
||||
gradle-builds
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
./gradlew :app:assembleDebug
|
||||
./gradlew :app:assembleRelease
|
||||
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
|
||||
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
|
||||
- name: Upload Artifacts(debug)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{ env.DEBUG_APK_FILE }}
|
||||
name: app-debug
|
||||
- name: Upload Artifacts(release)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{ env.RELEASE_APK_FILE }}
|
||||
name: app-release
|
62
.github/workflows/pull_request_ci.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Pull Request Checker
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**.txt'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Pull request check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup cmake
|
||||
uses: jwlawson/actions-setup-cmake@v1
|
||||
with:
|
||||
cmake-version: '3.22.1'
|
||||
- name: Prepare Java 11
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 11
|
||||
java-package: jdk
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
- name: Cache Gradle Dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
!~/.gradle/caches/build-cache-*
|
||||
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
|
||||
restore-keys: |
|
||||
gradle-deps
|
||||
- name: Cache Gradle Build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches/build-cache-*
|
||||
key: gradle-builds-core-${{ github.sha }}
|
||||
restore-keys: |
|
||||
gradle-builds
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
./gradlew :app:assembleDebug
|
||||
./gradlew :app:assembleRelease
|
||||
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
|
||||
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
|
||||
- name: Upload Artifacts(debug)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{ env.DEBUG_APK_FILE }}
|
||||
name: app-debug
|
||||
- name: Upload Artifacts(release)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{ env.RELEASE_APK_FILE }}
|
||||
name: app-release
|
BIN
.idea/icon.png
generated
Normal file
After Width: | Height: | Size: 12 KiB |
6
.idea/kotlinc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.7.20" />
|
||||
</component>
|
||||
</project>
|
35
README.md
@@ -2,12 +2,12 @@
|
||||
|
||||
[](https://github.com/fankes/TSBattery)
|
||||
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
||||
[](https://github.com/fankes/TSBattery/releases)
|
||||
[](https://github.com/fankes/TSBattery/releases)
|
||||
[](https://github.com/fankes/TSBattery/releases)
|
||||
[](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
||||
[](https://t.me/XiaofangInternet)
|
||||
<br/><br/>
|
||||
<br/>
|
||||
<br/>
|
||||
A new way to save your battery avoid cancer apps hacker it.
|
||||
|
||||
TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed 模块。
|
||||
@@ -32,10 +32,35 @@ TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed
|
||||
|
||||
## 请勿用于非法用途
|
||||
|
||||
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
||||
本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
||||
|
||||
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)、
|
||||
[Release](https://github.com/fankes/TSBattery/releases) 及 [蓝奏云](https://fankes.lanzouy.com/b02zfz3sj),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
||||
## 发行渠道说明
|
||||
|
||||
- [Automatic Build on Commit](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml)
|
||||
|
||||
上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **Github Actions** 进行查看,本更新由开源的流程自动编译发布,**不保证其稳定性**,所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。
|
||||
|
||||
- [Release](https://github.com/fankes/TSBattery/releases)
|
||||
- [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
||||
- [蓝奏云 **密码:tsbt**](https://fankes.lanzouy.com/b02zfz3sj)
|
||||
|
||||
上述更新为手动发布的稳定版,具体更新内容可点击上方的文字前往指定的发布页面查看,稳定版的更新将会同时发布到上述地址中,同步更新。
|
||||
|
||||
本模块发布地址仅限于上述所列出的地址,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
||||
|
||||
## 发行状态说明
|
||||
|
||||

|
||||
|
||||
上述状态为当前稳定版与自动构建版本一致或当前代码改动与稳定版无功能差异。
|
||||
|
||||

|
||||
|
||||
上述状态为存在自动构建版本和新功能的更新但当前并未发布稳定版,处于预发行状态。
|
||||
|
||||

|
||||
|
||||
上述状态为当前发行的稳定版可能存在严重问题但并未及时进行修复且并未发布稳定版。
|
||||
|
||||
## 开始贡献
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'com.google.devtools.ksp' version '1.7.10-1.0.6'
|
||||
id 'com.google.devtools.ksp' version '1.7.22-1.0.8'
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -59,15 +59,15 @@ android {
|
||||
|
||||
dependencies {
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
implementation 'com.highcapable.yukihookapi:api:1.1.2'
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.2'
|
||||
implementation 'com.highcapable.yukihookapi:api:1.1.5'
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.5'
|
||||
implementation 'com.github.duanhong169:drawabletoolbox:1.0.7'
|
||||
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
|
||||
implementation 'androidx.core:core-ktx:1.9.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.7.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
}
|
@@ -11,6 +11,10 @@
|
||||
<package android:name="com.tencent.mobileqq" />
|
||||
<package android:name="com.tencent.tim" />
|
||||
<package android:name="com.tencent.mm" />
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<application
|
||||
|
@@ -32,13 +32,10 @@ import com.highcapable.yukihookapi.hook.factory.encase
|
||||
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
companion object {
|
||||
object HookEntry : IYukiHookXposedInit {
|
||||
|
||||
/** 是否完全支持当前版本 */
|
||||
var isHookClientSupport = true
|
||||
}
|
||||
|
||||
override fun onInit() = configs {
|
||||
debugLog { tag = "TSBattery" }
|
||||
@@ -47,8 +44,7 @@ class HookEntry : IYukiHookXposedInit {
|
||||
}
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadApp(PackageName.QQ) { loadHooker(QQTIMHooker) }
|
||||
loadApp(PackageName.TIM) { loadHooker(QQTIMHooker) }
|
||||
loadApp(PackageName.WECHAT) { loadHooker(WeChatHooker) }
|
||||
loadApp(PackageName.QQ, PackageName.TIM) { loadHooker(QQTIMHooker) }
|
||||
loadApp(PackageName.WECHAT, WeChatHooker)
|
||||
}
|
||||
}
|
@@ -28,6 +28,7 @@ import android.os.Build
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.fankes.tsbattery.BuildConfig
|
||||
import com.fankes.tsbattery.const.PackageName
|
||||
import com.fankes.tsbattery.data.ConfigData
|
||||
@@ -35,14 +36,15 @@ import com.fankes.tsbattery.hook.HookEntry
|
||||
import com.fankes.tsbattery.hook.factory.hookSystemWakeLock
|
||||
import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
|
||||
import com.fankes.tsbattery.hook.factory.startModuleSettings
|
||||
import com.fankes.tsbattery.utils.factory.appVersionName
|
||||
import com.fankes.tsbattery.utils.factory.dp
|
||||
import com.fankes.tsbattery.utils.factory.versionName
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.*
|
||||
import com.highcapable.yukihookapi.hook.log.loggerD
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.type.android.*
|
||||
import com.highcapable.yukihookapi.hook.type.java.*
|
||||
|
||||
@@ -57,6 +59,9 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
/** QQ、TIM 存在的类 */
|
||||
private const val QQSettingSettingActivityClass = "${PackageName.QQ}.activity.QQSettingSettingActivity"
|
||||
|
||||
/** QQ 新版存在的类 (Pad 模式) */
|
||||
private const val QQSettingSettingFragmentClass = "${PackageName.QQ}.fragment.QQSettingSettingFragment"
|
||||
|
||||
/** QQ、TIM 存在的类 */
|
||||
private const val AboutActivityClass = "${PackageName.QQ}.activity.AboutActivity"
|
||||
|
||||
@@ -76,6 +81,9 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
private val BaseChatPieClass =
|
||||
VariousClass("${PackageName.QQ}.activity.aio.core.BaseChatPie", "${PackageName.QQ}.activity.BaseChatPie")
|
||||
|
||||
/** 一个内部进程的名称 (与 X5 浏览器内核有关) */
|
||||
private val privilegedProcessName = "$packageName:privileged_process"
|
||||
|
||||
/** 默认的 [Configuration] */
|
||||
var baseConfiguration: Configuration? = null
|
||||
|
||||
@@ -86,7 +94,13 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
private val isQQ get() = packageName == PackageName.QQ
|
||||
|
||||
/** 当前宿主的版本 */
|
||||
private var appVersionName = "<unknown>"
|
||||
private var hostVersionName = "<unknown>"
|
||||
|
||||
/**
|
||||
* 通过 [Activity] or [Fragment] 实例得到上下文
|
||||
* @return [Activity] or null
|
||||
*/
|
||||
private fun Any.compatToActivity() = if (this is Activity) this else current().method { name = "getActivity"; superClass() }.invoke()
|
||||
|
||||
/**
|
||||
* 这个类 QQ 的 BaseChatPie 是控制聊天界面的
|
||||
@@ -106,7 +120,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* - ❗Hook 错了方法会造成闪退!
|
||||
*/
|
||||
private fun hookQQBaseChatPie() {
|
||||
if (isQQ) when (appVersionName) {
|
||||
if (isQQ) when (hostVersionName) {
|
||||
"8.0.0" -> {
|
||||
hookBaseChatPie(methodName = "bq")
|
||||
hookBaseChatPie(methodName = "aL")
|
||||
@@ -215,9 +229,21 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
hookBaseChatPie(methodName = "y3")
|
||||
hookBaseChatPie(methodName = "H")
|
||||
}
|
||||
"8.9.15", "8.9.18", "8.9.19", "8.9.20" -> {
|
||||
hookBaseChatPie(methodName = "w3")
|
||||
hookBaseChatPie(methodName = "H")
|
||||
}
|
||||
"8.9.23", "8.9.25" -> {
|
||||
hookBaseChatPie(methodName = "z3")
|
||||
hookBaseChatPie(methodName = "H")
|
||||
}
|
||||
"8.9.28" -> {
|
||||
hookBaseChatPie(methodName = "A3")
|
||||
hookBaseChatPie(methodName = "H")
|
||||
}
|
||||
else -> {
|
||||
HookEntry.isHookClientSupport = false
|
||||
loggerD(msg = "$appVersionName not supported!")
|
||||
loggerW(msg = "$hostVersionName not supported!")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,7 +334,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
injectMember {
|
||||
method {
|
||||
name = "a"
|
||||
param(StringType, LongType)
|
||||
param(StringClass, LongType)
|
||||
returnType = UnitType
|
||||
}
|
||||
intercept()
|
||||
@@ -375,7 +401,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onHook"
|
||||
param(StringType, AnyType, AnyArrayClass, AnyType)
|
||||
param(StringClass, AnyClass, AnyArrayClass, AnyClass)
|
||||
}
|
||||
intercept()
|
||||
}
|
||||
@@ -478,14 +504,14 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onWriteLog"
|
||||
param(StringType, StringType)
|
||||
param(StringClass, StringClass)
|
||||
}
|
||||
intercept()
|
||||
}
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCmdRequest"
|
||||
param(StringType)
|
||||
param(StringClass)
|
||||
}
|
||||
intercept()
|
||||
}
|
||||
@@ -506,13 +532,52 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
}.ignoredHookClassNotFoundFailure()
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook QQ 的设置界面添加模块设置入口
|
||||
* @param instance 当前设置界面实例
|
||||
*/
|
||||
private fun hookQQSettingsUI(instance: Any?) {
|
||||
/** 当前的顶级 Item 实例 */
|
||||
val formItemRefRoot = instance?.current()?.field {
|
||||
type { it.name == FormSimpleItemClass || it.name == FormCommonSingleLineItemClass }.index(num = 1)
|
||||
}?.cast<View?>()
|
||||
/** 创建一个新的 Item */
|
||||
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance?.compatToActivity()) { param(ContextClass) }?.current {
|
||||
method {
|
||||
name = "setLeftText"
|
||||
param(CharSequenceClass)
|
||||
}.call("TSBattery")
|
||||
method {
|
||||
name = "setRightText"
|
||||
param(CharSequenceClass)
|
||||
}.call("${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})")
|
||||
method {
|
||||
name = "setBgType"
|
||||
param(IntType)
|
||||
}.call(if (isQQ) 0 else 2)
|
||||
}?.apply { setOnClickListener { context.startModuleSettings() } }?.also { item ->
|
||||
var listGroup = formItemRefRoot?.parent as? ViewGroup?
|
||||
val lparam = (if (listGroup?.childCount == 1) {
|
||||
listGroup = listGroup.parent as? ViewGroup
|
||||
(formItemRefRoot?.parent as? View?)?.layoutParams
|
||||
} else formItemRefRoot?.layoutParams)
|
||||
?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
/** 设置圆角和间距 */
|
||||
if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
|
||||
/** 将 Item 添加到设置界面 */
|
||||
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
onAppLifecycle {
|
||||
onAppLifecycle(isOnFailureThrowToApp = false) {
|
||||
attachBaseContext { baseContext, hasCalledSuper ->
|
||||
if (hasCalledSuper.not()) baseConfiguration = baseContext.resources.configuration
|
||||
}
|
||||
onCreate {
|
||||
appVersionName = versionName
|
||||
hostVersionName = appVersionName
|
||||
/** 不注入此进程防止部分系统发生 X5 浏览器内核崩溃问题 */
|
||||
if (processName.startsWith(privilegedProcessName)) return@onCreate
|
||||
ConfigData.init(context = this)
|
||||
registerModuleAppActivities(AboutActivityClass)
|
||||
if (ConfigData.isDisableAllHook) return@onCreate
|
||||
@@ -535,49 +600,26 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
afterHook { instance<Activity>().jumpToModuleSettings() }
|
||||
}
|
||||
}
|
||||
/** 将条目注入设置界面 */
|
||||
/** 将条目注入设置界面 (Activity) */
|
||||
QQSettingSettingActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "doOnCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
/** 当前的顶级 Item 实例 */
|
||||
val formItemRefRoot = field {
|
||||
type(FormSimpleItemClass).index(num = 1)
|
||||
}.ignored().get(instance).cast() ?: field {
|
||||
type(FormCommonSingleLineItemClass).index(num = 1)
|
||||
}.ignored().get(instance).cast<View?>()
|
||||
/** 创建一个新的 Item */
|
||||
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance) { param(ContextClass) }?.current {
|
||||
afterHook { hookQQSettingsUI(instance) }
|
||||
}
|
||||
}
|
||||
/** 将条目注入设置界面 (Fragment) */
|
||||
QQSettingSettingFragmentClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "setLeftText"
|
||||
param(CharSequenceType)
|
||||
}.call("TSBattery")
|
||||
method {
|
||||
name = "setRightText"
|
||||
param(CharSequenceType)
|
||||
}.call(BuildConfig.VERSION_NAME)
|
||||
method {
|
||||
name = "setBgType"
|
||||
param(IntType)
|
||||
}.call(if (isQQ) 0 else 2)
|
||||
}?.apply { setOnClickListener { instance<Activity>().startModuleSettings() } }?.also { item ->
|
||||
var listGroup = formItemRefRoot?.parent as? ViewGroup?
|
||||
val lparam = (if (listGroup?.childCount == 1) {
|
||||
listGroup = listGroup.parent as? ViewGroup
|
||||
(formItemRefRoot?.parent as? View?)?.layoutParams
|
||||
} else formItemRefRoot?.layoutParams)
|
||||
?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
/** 设置圆角和间距 */
|
||||
if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
|
||||
/** 将 Item 添加到设置界面 */
|
||||
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
name = "doOnCreateView"
|
||||
paramCount = 3
|
||||
}
|
||||
afterHook { hookQQSettingsUI(instance) }
|
||||
}
|
||||
}.ignoredHookClassNotFoundFailure()
|
||||
}
|
||||
}
|
||||
}
|
@@ -22,8 +22,10 @@
|
||||
package com.fankes.tsbattery.hook.entity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
@@ -35,16 +37,16 @@ import com.fankes.tsbattery.hook.factory.hookSystemWakeLock
|
||||
import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
|
||||
import com.fankes.tsbattery.hook.factory.startModuleSettings
|
||||
import com.fankes.tsbattery.utils.factory.absoluteStatusBarHeight
|
||||
import com.fankes.tsbattery.utils.factory.appVersionCode
|
||||
import com.fankes.tsbattery.utils.factory.appVersionName
|
||||
import com.fankes.tsbattery.utils.factory.dp
|
||||
import com.fankes.tsbattery.utils.factory.versionCode
|
||||
import com.fankes.tsbattery.utils.factory.versionName
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
|
||||
import com.highcapable.yukihookapi.hook.factory.processName
|
||||
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import com.highcapable.yukihookapi.hook.type.android.BundleClass
|
||||
import com.highcapable.yukihookapi.hook.type.android.ViewClass
|
||||
|
||||
/**
|
||||
* Hook 微信
|
||||
@@ -65,6 +67,30 @@ object WeChatHooker : YukiBaseHooker() {
|
||||
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||
private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI"
|
||||
|
||||
/** TSBattery 图标 TAG 名称 */
|
||||
private const val TSBARRERY_ICON_TAG = "tsbattery_icon"
|
||||
|
||||
/**
|
||||
* 创建 TSBattery 图标
|
||||
* @param context 当前实例
|
||||
* @return [LinearLayout]
|
||||
*/
|
||||
private fun createPreferenceIcon(context: Context) = LinearLayout(context).apply {
|
||||
tag = TSBARRERY_ICON_TAG
|
||||
gravity = Gravity.END or Gravity.BOTTOM
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
addView(ImageView(context).apply {
|
||||
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply {
|
||||
topMargin = context.absoluteStatusBarHeight + 15.dp(context)
|
||||
rightMargin = 20.dp(context)
|
||||
}
|
||||
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null))
|
||||
setImageResource(R.drawable.ic_icon)
|
||||
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置"
|
||||
setOnClickListener { context.startModuleSettings() }
|
||||
})
|
||||
}
|
||||
|
||||
override fun onHook() {
|
||||
onAppLifecycle {
|
||||
onCreate {
|
||||
@@ -73,7 +99,7 @@ object WeChatHooker : YukiBaseHooker() {
|
||||
when {
|
||||
EmptyActivityClass.hasClass() -> EmptyActivityClass
|
||||
WelabMainUIClass.hasClass() -> WelabMainUIClass
|
||||
else -> error("Inject WeChat Activity Proxy failed, unsupport version $versionName($versionCode)")
|
||||
else -> error("Inject WeChat Activity Proxy failed, unsupport version $appVersionName($appVersionCode)")
|
||||
}
|
||||
)
|
||||
if (ConfigData.isDisableAllHook) return@onCreate
|
||||
@@ -97,32 +123,26 @@ object WeChatHooker : YukiBaseHooker() {
|
||||
SettingsUIClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
name = "onResume"
|
||||
emptyParam()
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "get_fragment"
|
||||
emptyParam()
|
||||
superClass(isOnlySuperClass = true)
|
||||
}.get(instance).call()?.current()
|
||||
?.field { name = "mController" }
|
||||
?.current()?.method { name = "getContentView" }
|
||||
?.invoke<ViewGroup>()?.addView(LinearLayout(instance()).apply {
|
||||
context.injectModuleAppResources()
|
||||
gravity = Gravity.END or Gravity.BOTTOM
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
addView(ImageView(context).apply {
|
||||
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply {
|
||||
topMargin = context.absoluteStatusBarHeight + 15.dp(context)
|
||||
rightMargin = 20.dp(context)
|
||||
}
|
||||
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null))
|
||||
setImageResource(R.drawable.ic_icon)
|
||||
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置"
|
||||
setOnClickListener { context.startModuleSettings() }
|
||||
})
|
||||
})
|
||||
}.get(instance).call()?.current()?.method {
|
||||
name = "getView"
|
||||
emptyParam()
|
||||
returnType = ViewClass
|
||||
superClass(isOnlySuperClass = true)
|
||||
}?.invoke<ViewGroup?>()?.also {
|
||||
it.context?.injectModuleAppResources()
|
||||
runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView ->
|
||||
if (rootView.findViewWithTag<View>(TSBARRERY_ICON_TAG) == null)
|
||||
rootView.addView(createPreferenceIcon(it.context))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ private fun Context.isQQNightMode() = runCatching {
|
||||
paramCount = 1
|
||||
}.get().string(MobileQQClass.toClass(classLoader)
|
||||
.field { name = "sMobileQQ" }.ignored().get().current(ignored = true)?.field { name = "mAppRuntime" }?.any()
|
||||
).let { it.endsWith(suffix = "1103") || it.endsWith(suffix = "2920") }
|
||||
).let { it.endsWith("1103") || it.endsWith("2920") }
|
||||
}.getOrNull() ?: false
|
||||
|
||||
/** 启动模块设置 [Activity] */
|
||||
|
@@ -53,7 +53,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
"8.8.20", "8.8.23", "8.8.28", "8.8.33", "8.8.35", "8.8.38", "8.8.50",
|
||||
"8.8.55", "8.8.68", "8.8.80", "8.8.83", "8.8.85", "8.8.88", "8.8.90",
|
||||
"8.8.93", "8.8.95", "8.8.98", "8.9.0", "8.9.1", "8.9.2", "8.9.3",
|
||||
"8.9.5", "8.9.8", "8.9.10", "8.9.13"
|
||||
"8.9.5", "8.9.8", "8.9.10", "8.9.13", "8.9.15", "8.9.18", "8.9.19",
|
||||
"8.9.20", "8.9.23", "8.9.25", "8.9.28"
|
||||
)
|
||||
private val qqSupportVersion by lazy {
|
||||
if (qqSupportVersions.isNotEmpty()) {
|
||||
@@ -62,8 +63,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
"${value.trim().let { it.substring(0, it.lastIndex) }}\n\n其余版本请自行测试是否有效。"
|
||||
} else "empty"
|
||||
}
|
||||
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
|
||||
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
|
||||
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)。"
|
||||
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼。"
|
||||
|
||||
/** 预发布的版本标识 */
|
||||
private const val pendingFlag = ""
|
||||
@@ -81,7 +82,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
/** 判断 Hook 状态 */
|
||||
if (YukiHookAPI.Status.isModuleActive) {
|
||||
binding.mainLinStatus.setBackgroundResource(R.drawable.bg_green_round)
|
||||
binding.mainImgStatus.setImageResource(R.mipmap.ic_success)
|
||||
binding.mainImgStatus.setImageResource(R.drawable.ic_success)
|
||||
binding.mainTextStatus.text = "模块已激活"
|
||||
binding.mainTextApiWay.isVisible = true
|
||||
refreshActivateExecutor()
|
||||
@@ -95,9 +96,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
noCancelable()
|
||||
}
|
||||
/** 设置安装状态 */
|
||||
binding.mainTextQqVer.text = if (PackageName.QQ.isInstall) version(PackageName.QQ) else "未安装"
|
||||
binding.mainTextTimVer.text = if (PackageName.TIM.isInstall) version(PackageName.TIM) else "未安装"
|
||||
binding.mainTextWechatVer.text = if (PackageName.WECHAT.isInstall) version(PackageName.WECHAT) else "未安装"
|
||||
binding.mainTextQqVer.text = PackageName.QQ.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
|
||||
binding.mainTextTimVer.text = PackageName.TIM.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
|
||||
binding.mainTextWechatVer.text = PackageName.WECHAT.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
|
||||
/** 设置文本 */
|
||||
binding.mainTextVersion.text = "模块版本:${BuildConfig.VERSION_NAME} $pendingFlag"
|
||||
binding.mainQqItem.setOnClickListener {
|
||||
@@ -127,7 +128,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
/** 振动提醒 */
|
||||
it.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||
}
|
||||
/** 获取 Sp 存储的信息 */
|
||||
/** 设置桌面图标显示隐藏 */
|
||||
binding.hideIconInLauncherSwitch.isChecked = isLauncherIconShowing.not()
|
||||
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
|
||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||
@@ -152,7 +153,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
* @param packageName 包名
|
||||
*/
|
||||
private fun startModuleSettings(packageName: String) {
|
||||
if (packageName.isInstall) runCatching {
|
||||
if (isInstall(packageName)) runCatching {
|
||||
startActivity(Intent().apply {
|
||||
component = ComponentName(
|
||||
packageName,
|
||||
@@ -166,12 +167,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||
|
||||
/** 刷新模块激活使用的方式 */
|
||||
private fun refreshActivateExecutor() {
|
||||
when {
|
||||
YukiHookAPI.Status.executorVersion > 0 ->
|
||||
binding.mainTextApiWay.text =
|
||||
"Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
|
||||
YukiHookAPI.Status.isTaiChiModuleActive -> binding.mainTextApiWay.text = "Activated by TaiChi"
|
||||
else -> binding.mainTextApiWay.text = "Activated by anonymous"
|
||||
}
|
||||
if (YukiHookAPI.Status.Executor.apiLevel > 0)
|
||||
binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.Executor.name} API ${YukiHookAPI.Status.Executor.apiLevel}"
|
||||
else binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.Executor.name}"
|
||||
}
|
||||
}
|
@@ -40,6 +40,7 @@ import com.fankes.tsbattery.ui.activity.MainActivity
|
||||
import com.fankes.tsbattery.ui.activity.base.BaseActivity
|
||||
import com.fankes.tsbattery.utils.factory.*
|
||||
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
@@ -70,20 +71,21 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
}
|
||||
}
|
||||
binding.titleNameText.text = "TSBattery 设置 (${appName.trim()})"
|
||||
binding.appIcon.setImageDrawable(findAppIcon())
|
||||
binding.appIcon.setImageDrawable(appIconOf())
|
||||
binding.appName.text = appName.trim()
|
||||
binding.appVersion.text = "${versionName}($versionCode)"
|
||||
binding.appVersion.text = "${appVersionName}($appVersionCode)"
|
||||
binding.moduleVersion.text = "${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"
|
||||
binding.activeModeIcon.isVisible = HookEntry.isHookClientSupport
|
||||
binding.inactiveModeIcon.isGone = HookEntry.isHookClientSupport
|
||||
binding.unsupportItem.isGone = HookEntry.isHookClientSupport
|
||||
binding.executorInfoText.text = "${YukiHookAPI.Status.Executor.name} API ${YukiHookAPI.Status.Executor.apiLevel}"
|
||||
/** 刷新当前模式文本 */
|
||||
fun refreshCurrentModeText() {
|
||||
binding.currentModeText.text = when {
|
||||
ConfigData.isDisableAllHook -> "模块已停用"
|
||||
packageName == PackageName.WECHAT -> "仅限基础省电模式"
|
||||
ConfigData.isEnableQQTimProtectMode -> "已启用保守模式"
|
||||
else -> "已启用完全模式"
|
||||
packageName == PackageName.WECHAT -> "基础省电模式"
|
||||
ConfigData.isEnableQQTimProtectMode -> "保守模式"
|
||||
else -> "完全模式"
|
||||
}
|
||||
}
|
||||
refreshCurrentModeText()
|
||||
@@ -116,7 +118,7 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
|
||||
/** 替换占位符到当前 APP 名称 */
|
||||
private fun TextView.replaceToAppName() {
|
||||
text = text.toString().replace(oldValue = "{APP_NAME}", appName)
|
||||
text = text.toString().replace("{APP_NAME}", appName)
|
||||
}
|
||||
|
||||
/** 重新设置 DPI 防止 QQ、TIM 修改它 */
|
||||
@@ -134,5 +136,5 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
* 获取当前 APP 名称
|
||||
* @return [String]
|
||||
*/
|
||||
private val appName by lazy { findAppName().let { if (packageName == PackageName.WECHAT) it else " $it " } }
|
||||
private val appName by lazy { appNameOf().let { if (packageName == PackageName.WECHAT) it else " $it " } }
|
||||
}
|
@@ -19,7 +19,7 @@
|
||||
*
|
||||
* This file is Created by fankes on 2022/1/7.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION", "unused", "DiscouragedApi", "InternalInsetResource")
|
||||
@file:Suppress("unused", "DiscouragedApi", "InternalInsetResource")
|
||||
|
||||
package com.fankes.tsbattery.utils.factory
|
||||
|
||||
@@ -29,14 +29,17 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.PackageInfoFlags
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import com.fankes.tsbattery.BuildConfig
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
|
||||
@@ -66,76 +69,75 @@ val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Confi
|
||||
inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
|
||||
|
||||
/**
|
||||
* 得到安装包信息
|
||||
* @return [PackageInfo]
|
||||
* 得到 APP 安装包信息 (兼容)
|
||||
* @param packageName APP 包名
|
||||
* @param flag [PackageInfoFlags]
|
||||
* @return [PackageInfo] or null
|
||||
*/
|
||||
val Context.packageInfo get() = packageManager?.getPackageInfo(packageName, 0) ?: PackageInfo()
|
||||
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
|
||||
@Suppress("DEPRECATION")
|
||||
if (Build.VERSION.SDK_INT >= 33)
|
||||
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
|
||||
else packageManager?.getPackageInfo(packageName, flag.toInt())
|
||||
}.getOrNull()
|
||||
|
||||
/**
|
||||
* 判断应用是否安装
|
||||
* @return [Boolean]
|
||||
*/
|
||||
val String.isInstall
|
||||
get() = try {
|
||||
appContext.packageManager.getPackageInfo(
|
||||
this,
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES
|
||||
)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到版本信息
|
||||
* @return [String]
|
||||
*/
|
||||
val Context.versionName get() = packageInfo.versionName ?: ""
|
||||
|
||||
/**
|
||||
* 得到版本号
|
||||
* 得到 APP 版本号 (兼容 [PackageInfo.getLongVersionCode])
|
||||
* @return [Int]
|
||||
*/
|
||||
val Context.versionCode get() = packageInfo.versionCode
|
||||
private val PackageInfo.versionCodeCompat get() = PackageInfoCompat.getLongVersionCode(this)
|
||||
|
||||
/**
|
||||
* 得到版本信息与版本号
|
||||
* @param packageName 包名
|
||||
* 判断 APP 是否安装
|
||||
* @param packageName APP 包名
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun Context.isInstall(packageName: String) = getPackageInfoCompat(packageName)?.let { true } ?: false
|
||||
|
||||
/**
|
||||
* 得到 APP 版本信息
|
||||
* @return [String]
|
||||
*/
|
||||
fun Context.version(packageName: String) = safeOfNothing {
|
||||
packageManager?.getPackageInfo(packageName, 0)?.let {
|
||||
"${it.versionName}(${it.versionCode})"
|
||||
} ?: ""
|
||||
}
|
||||
val Context.appVersionName get() = getPackageInfoCompat(packageName)?.versionName ?: ""
|
||||
|
||||
/**
|
||||
* 得到 APP 版本号
|
||||
* @return [Int]
|
||||
*/
|
||||
val Context.appVersionCode get() = getPackageInfoCompat(packageName)?.versionCodeCompat
|
||||
|
||||
/**
|
||||
* 得到 APP 版本信息与版本号
|
||||
* @param packageName APP 包名 - 默认为当前 APP
|
||||
* @return [String]
|
||||
*/
|
||||
fun Context.appVersionBrandOf(packageName: String = getPackageName()) =
|
||||
getPackageInfoCompat(packageName)?.let { "${it.versionName}(${it.versionCodeCompat})" } ?: ""
|
||||
|
||||
/**
|
||||
* 得到 APP 名称
|
||||
* @param name APP 包名 - 默认为当前 APP
|
||||
* @param packageName APP 包名 - 默认为当前 APP
|
||||
* @return [String]
|
||||
*/
|
||||
fun Context.findAppName(name: String = packageName) =
|
||||
safeOfNothing { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadLabel(packageManager).toString() }
|
||||
fun Context.appNameOf(packageName: String = getPackageName()) =
|
||||
getPackageInfoCompat(packageName)?.applicationInfo?.loadLabel(packageManager)?.toString() ?: ""
|
||||
|
||||
/**
|
||||
* 得到 APP 图标
|
||||
* @param name APP 包名 - 默认为当前 APP
|
||||
* @param packageName APP 包名 - 默认为当前 APP
|
||||
* @return [Drawable] or null
|
||||
*/
|
||||
fun Context.findAppIcon(name: String = packageName) =
|
||||
safeOfNull { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadIcon(packageManager) }
|
||||
fun Context.appIconOf(packageName: String = getPackageName()) = getPackageInfoCompat(packageName)?.applicationInfo?.loadIcon(packageManager)
|
||||
|
||||
/**
|
||||
* 网络连接是否正常
|
||||
* @return [Boolean] 网络是否连接
|
||||
*/
|
||||
val isNetWorkSuccess get() = appContext.isNetWorkSuccess
|
||||
|
||||
/**
|
||||
* 网络连接是否正常
|
||||
* @return [Boolean] 网络是否连接
|
||||
*/
|
||||
val Context.isNetWorkSuccess get() = safeOfFalse { getSystemService<ConnectivityManager>()?.activeNetworkInfo != null }
|
||||
val Context.isNetWorkSuccess
|
||||
get() = safeOfFalse {
|
||||
@Suppress("DEPRECATION")
|
||||
getSystemService<ConnectivityManager>()?.activeNetworkInfo != null
|
||||
}
|
||||
|
||||
/**
|
||||
* dp 转换为 pxInt
|
||||
@@ -190,7 +192,7 @@ fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {
|
||||
* @param packageName 包名
|
||||
*/
|
||||
fun Context.openSelfSetting(packageName: String = appContext.packageName) = runCatching {
|
||||
if (packageName.isInstall)
|
||||
if (isInstall(packageName))
|
||||
startActivity(Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
|
@@ -103,7 +103,7 @@ object GithubReleaseTool {
|
||||
(context as? Activity?)?.runOnUiThread {
|
||||
context.showDialog {
|
||||
title = "网络不可用"
|
||||
msg = "模块的联网权限可能已被禁用,请开启联网权限以定期检查更新。"
|
||||
msg = "应用的联网权限可能已被禁用,请开启联网权限以定期检查更新。"
|
||||
confirmButton(text = "去开启") { context.openSelfSetting() }
|
||||
cancelButton()
|
||||
noCancelable()
|
||||
@@ -121,10 +121,10 @@ object GithubReleaseTool {
|
||||
* 格式化时间为本地时区
|
||||
* @return [String] 本地时区时间
|
||||
*/
|
||||
private fun String.localTime() = replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "").let {
|
||||
private fun String.localTime() = replace("T", " ").replace("Z", "").let {
|
||||
runCatching {
|
||||
val local = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
|
||||
val current = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
|
||||
val local = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
|
||||
val current = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
|
||||
local.format(current.parse(it))
|
||||
}.getOrNull() ?: it
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ object YukiPromoteTool {
|
||||
context.showDialog {
|
||||
title = "面向开发者的推广"
|
||||
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
|
||||
"快来体验 YukiHookAPI,这是一个使用 Kotlin 重新构建的高效 Xposed Hook API,助你的开发变得更轻松。"
|
||||
"快来体验 YukiHookAPI,这是一个使用 Kotlin 构建的高效 Hook API 与 Xposed 模块解决方案,助你的开发变得更轻松。"
|
||||
confirmButton(text = "去看看") {
|
||||
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
|
||||
saveReaded()
|
||||
|
9
app/src/main/res/drawable/ic_about.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150.1dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1025"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M983.8,314.4c-25.7,-60.8 -62.5,-115.4 -109.4,-162.3 -46.9,-46.9 -101.5,-83.7 -162.3,-109.4 -62.9,-26.7 -129.9,-40.2 -198.8,-40.2S377.5,16 314.5,42.7C253.8,68.4 199.1,105.2 152.3,152.2c-46.9,46.9 -83.7,101.5 -109.4,162.3 -26.7,62.9 -40.2,129.9 -40.2,198.8s13.5,135.8 40.2,198.8c25.7,60.8 62.5,115.4 109.4,162.3 46.9,46.9 101.5,83.7 162.3,109.4 62.9,26.7 129.9,40.2 198.8,40.2s135.8,-13.5 198.8,-40.2c60.8,-25.7 115.4,-62.5 162.3,-109.4 46.9,-46.9 83.7,-101.5 109.4,-162.3 26.7,-62.9 40.2,-129.9 40.2,-198.8s-13.6,-135.9 -40.3,-198.9zM550.5,768.2c0,21 -17,38 -38,38s-38,-17 -38,-38L474.5,395.6c0,-21 17,-38 38,-38s38,17 38,38v372.6zM510.8,305.5c-29.2,0 -52.7,-23.7 -52.7,-52.7 0,-29.2 23.7,-52.7 52.7,-52.7 29.2,0 52.7,23.7 52.7,52.7 0.1,29.2 -23.6,52.7 -52.7,52.7z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_back.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="192dp"
|
||||
android:height="150.39165dp"
|
||||
android:viewportWidth="1307"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M268.7,566.5h929.6c36.3,0 72.6,-29 72.6,-72.6 0,-36.3 -29,-72.6 -72.6,-72.6H305l297.8,-297.8c29,-29 29,-72.6 0,-101.7 -29,-29 -72.6,-29 -101.7,0L72.6,450.3c-14.5,14.5 -21.8,36.3 -21.8,58.1 0,21.8 0,43.6 21.8,58.1l428.5,428.5c29,29 72.6,29 101.7,0 29,-29 29,-72.6 0,-101.7l-334.1,-326.8z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_error.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="896"
|
||||
android:viewportHeight="896">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M448,0C200.58,0 0,200.58 0,448 0,695.42 200.58,896 448,896 695.42,896 896,695.42 896,448 896,200.58 695.42,0 448,0ZM663,612.05a36.11,36.11 0,0 1,0 50.95,36.11 36.11,0 0,1 -50.91,0L448,498.91 284,663a36.11,36.11 0,0 1,-51 0,36.11 36.11,0 0,1 0,-50.91L397,448.09 233,284a36.11,36.11 0,0 1,0 -51,36.11 36.11,0 0,1 51,0l164,164.09 164,-164a36.11,36.11 0,0 1,51 -0.09,36.11 36.11,0 0,1 0,51L498.91,448Z" />
|
||||
</vector>
|
12
app/src/main/res/drawable/ic_fast_op.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,4H37L26,18H41L17,44L22,25H8L19,4Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_github.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M512,12.6c-282.8,0 -512,229.2 -512,512 0,226.2 146.7,418.1 350.1,485.8 25.6,4.7 35,-11.1 35,-24.6 0,-12.2 -0.5,-52.5 -0.7,-95.3 -142.5,31 -172.5,-60.4 -172.5,-60.4 -23.3,-59.2 -56.8,-74.9 -56.8,-74.9 -46.5,-31.8 3.5,-31.1 3.5,-31.1 51.4,3.6 78.5,52.8 78.5,52.8 45.7,78.3 119.8,55.6 149,42.6 4.6,-33.1 17.9,-55.7 32.5,-68.5 -113.7,-12.9 -233.3,-56.9 -233.3,-253 0,-55.9 20,-101.6 52.8,-137.4 -5.3,-12.9 -22.8,-65 5,-135.5 0,0 43,-13.8 140.8,52.5 40.8,-11.4 84.6,-17 128.2,-17.2 43.5,0.2 87.3,5.9 128.3,17.2 97.7,-66.2 140.6,-52.5 140.6,-52.5 27.9,70.5 10.3,122.6 5,135.5 32.8,35.8 52.7,81.5 52.7,137.4 0,196.6 -119.8,239.9 -233.8,252.6 18.4,15.9 34.7,47 34.7,94.8 0,68.5 -0.6,123.6 -0.6,140.5 0,13.6 9.2,29.6 35.2,24.6 203.3,-67.8 349.9,-259.6 349.9,-485.8 0,-282.8 -229.2,-512 -512,-512z" />
|
||||
</vector>
|
25
app/src/main/res/drawable/ic_home.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,18V42H39V18L24,6L9,18Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29V42H29V29H19Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,42H39"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round" />
|
||||
</vector>
|
30
app/src/main/res/drawable/ic_info.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M24,44C29.523,44 34.523,41.761 38.142,38.142C41.761,34.523 44,29.523 44,24C44,18.477 41.761,13.477 38.142,9.858C34.523,6.239 29.523,4 24,4C18.477,4 13.477,6.239 9.858,9.858C6.239,13.477 4,18.477 4,24C4,29.523 6.239,34.523 9.858,38.142C13.477,41.761 18.477,44 24,44Z"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M24,11C25.381,11 26.5,12.119 26.5,13.5C26.5,14.881 25.381,16 24,16C22.619,16 21.5,14.881 21.5,13.5C21.5,12.119 22.619,11 24,11Z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M24.5,34V20H23.5H22.5"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M21,34H28"
|
||||
android:strokeWidth="4"
|
||||
android:strokeColor="#ffffff"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
</vector>
|
@@ -3,7 +3,8 @@
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group android:scaleX="0.03609375"
|
||||
<group
|
||||
android:scaleX="0.03609375"
|
||||
android:scaleY="0.03609375"
|
||||
android:translateX="35.52"
|
||||
android:translateY="35.52">
|
||||
|
9
app/src/main/res/drawable/ic_success.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1008.7"
|
||||
android:viewportHeight="1008.7">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M504.4,0C226.3,0 0,226.3 0,504.4 0,782.5 226.3,1008.7 504.4,1008.7c278.1,0 504.4,-226.3 504.4,-504.4C1008.7,226.3 782.5,0 504.4,0ZM786.6,407.7 L458.6,743.9c-7.8,8 -18.6,12.6 -29.8,12.6h-0.2c-11.1,0 -21.8,-4.4 -29.7,-12.3L222.5,567.9c-16.4,-16.4 -16.4,-43 0,-59.4 16.4,-16.4 43,-16.4 59.4,0L428.2,654.8 726.5,348.9c16.3,-16.6 42.9,-16.9 59.4,-0.7 16.6,16.2 16.9,42.8 0.7,59.4z" />
|
||||
</vector>
|
9
app/src/main/res/drawable/ic_warn.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="150dp"
|
||||
android:height="150dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="m512,794a44.8,44.8 0,1 1,44.8 -44.8,44.8 44.8,0 0,1 -44.8,44.8zM471.9,230.8a40.1,40.1 0,0 1,80.2 0v369.1a40.1,40.1 0,0 1,-79.8 0zM512,0A512,512 0,1 0,1024 512,512 512,0 0,0 512,0Z" />
|
||||
</vector>
|
@@ -26,7 +26,7 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:src="@mipmap/ic_back"
|
||||
android:src="@drawable/ic_back"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="返回" />
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
android:id="@+id/active_mode_icon"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:src="@mipmap/ic_success"
|
||||
android:src="@drawable/ic_success"
|
||||
android:tint="#FF26A69A"
|
||||
android:visibility="gone" />
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
android:id="@+id/inactive_mode_icon"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:src="@mipmap/ic_error"
|
||||
android:src="@drawable/ic_error"
|
||||
android:tint="#FF7043"
|
||||
android:visibility="gone" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
@@ -204,7 +204,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="检测到未适配的版本"
|
||||
android:text="未适配"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
@@ -227,6 +227,26 @@
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="|"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/executor_info_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -355,7 +375,7 @@
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务(HMS)或(GMS)可以尝试关闭。"
|
||||
android:text="关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务 (HMS) 或 (MIPUSH) 可以尝试关闭。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
@@ -36,7 +36,7 @@
|
||||
android:layout_height="27dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/ic_github"
|
||||
android:src="@drawable/ic_github"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="项目地址" />
|
||||
</LinearLayout>
|
||||
@@ -59,7 +59,7 @@
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:src="@mipmap/ic_warn"
|
||||
android:src="@drawable/ic_warn"
|
||||
android:tint="@color/white" />
|
||||
|
||||
<LinearLayout
|
||||
@@ -250,7 +250,7 @@
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:alpha="0.85"
|
||||
android:src="@mipmap/ic_about"
|
||||
android:src="@drawable/ic_about"
|
||||
android:tint="@color/colorTextDark" />
|
||||
|
||||
<TextView
|
||||
@@ -282,11 +282,21 @@
|
||||
android:layout_marginBottom="10dp"
|
||||
android:gravity="center|start">
|
||||
|
||||
<ImageView
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/ic_shot_icon" />
|
||||
app:cardBackgroundColor="#FF00BCD4"
|
||||
app:cardCornerRadius="50dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:padding="2.5dp"
|
||||
android:src="@drawable/ic_fast_op" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@@ -364,11 +374,21 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center|start">
|
||||
|
||||
<ImageView
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/ic_home" />
|
||||
app:cardBackgroundColor="#FFFF9800"
|
||||
app:cardCornerRadius="50dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:padding="2.5dp"
|
||||
android:src="@drawable/ic_home" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@@ -428,11 +448,21 @@
|
||||
android:layout_marginBottom="15dp"
|
||||
android:gravity="center|start">
|
||||
|
||||
<ImageView
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/ic_help" />
|
||||
app:cardBackgroundColor="#FF03A9F4"
|
||||
app:cardCornerRadius="50dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:padding="2dp"
|
||||
android:src="@drawable/ic_info" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
@@ -470,7 +500,7 @@
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.8"
|
||||
android:lineSpacingExtra="10dp"
|
||||
android:text="Q.如何使用?\nA.目前模块支持 LSPosed、LSPatch 以及太极(无极)框架,在太极和 LSPosed 的作用域中,只需勾选 QQ、TIM、微信即可,模块可以做到即插即用,激活后无需重启手机,重启 QQ、TIM 或微信就可以了。"
|
||||
android:text="Q.如何使用?\nA.目前模块支持 LSPosed、LSPatch 以及太极和一些常见的免 Root 框架,在太极和 LSPosed 的作用域中,只需勾选 QQ、TIM、微信即可,模块可以做到即插即用,激活后无需重启手机,重启 QQ、TIM 或微信就可以了。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.0 KiB |
10
build.gradle
@@ -1,12 +1,12 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.3.0' apply false
|
||||
id 'com.android.library' version '7.3.0' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
|
||||
id 'com.android.application' version '7.3.1' apply false
|
||||
id 'com.android.library' version '7.3.1' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.22' apply false
|
||||
}
|
||||
|
||||
ext {
|
||||
appVersionName = "4.1"
|
||||
appVersionCode = 26
|
||||
appVersionName = "4.2"
|
||||
appVersionCode = 27
|
||||
enableR8 = true
|
||||
}
|
||||
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Wed May 25 04:34:58 CST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|