mirror of
https://github.com/LittleTurtle2333/SimplicityTools.git
synced 2026-07-13 03:41:19 +08:00
Compare commits
26 Commits
64c2ec4af1
...
yuki
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1af8e0605b | ||
|
|
29fa75cca0 | ||
|
|
84f826fc31 | ||
|
|
719e7dfac1 | ||
|
|
f77f9be2af | ||
|
|
c81951da2a | ||
|
|
074a0fa160 | ||
|
|
ab5abc10c9 | ||
|
|
8117809073 | ||
|
|
ce5312494c | ||
|
|
3ce5d1b1f2 | ||
|
|
2737cd2492 | ||
|
|
3d2e315113 | ||
|
|
3fbfaa218f | ||
|
|
51759aa199 | ||
|
|
7449d6e890 | ||
|
|
1b625d07eb | ||
|
|
d47aa371ab | ||
|
|
dae0b60c40 | ||
|
|
74df408148 | ||
|
|
62d2666c41 | ||
|
|
4f20d364c6 | ||
|
|
62f08e5bcf | ||
|
|
98876ddbd2 | ||
|
|
23832a4e0d | ||
|
|
582af167ed |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -15,5 +15,4 @@
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/app/release/app-release.apk
|
||||
/app/release/output-metadata.json
|
||||
/app/release/*
|
||||
@@ -14,8 +14,6 @@ android {
|
||||
versionCode 75
|
||||
versionName '1.7.5-Yuki'
|
||||
buildConfigField("String", "BUILD_TIME", "\"${System.currentTimeMillis()}\"")
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -44,6 +42,25 @@ android {
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
}
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
// 名称+当前版本号
|
||||
def fileName = "WooBoxForMIUI_v${defaultConfig.versionName}"
|
||||
|
||||
// 加入打包日期
|
||||
def releaseDate = new Date().format("MMddHHmmss", TimeZone.getDefault())
|
||||
fileName = fileName + "_${releaseDate}"
|
||||
|
||||
// 如果是debug版本,加入debug
|
||||
if ( variant.buildType.name =='debug') {
|
||||
fileName = fileName + "_debug"
|
||||
}else if(variant.buildType.name =='release') {
|
||||
fileName = fileName + "_release"
|
||||
}
|
||||
// 最终生成文件名
|
||||
output.outputFileName = fileName + ".apk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -11,6 +11,9 @@ import com.lt2333.simplicitytools.activity.pages.all.AboutPage
|
||||
import com.lt2333.simplicitytools.activity.pages.all.MenuPage
|
||||
import com.lt2333.simplicitytools.activity.pages.s.*
|
||||
import com.lt2333.simplicitytools.activity.pages.t.*
|
||||
import com.microsoft.appcenter.AppCenter
|
||||
import com.microsoft.appcenter.analytics.Analytics
|
||||
import com.microsoft.appcenter.crashes.Crashes
|
||||
import java.util.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@@ -19,6 +22,14 @@ class MainActivity : MIUIActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (!checkLSPosed()) isLoad = false
|
||||
super.onCreate(savedInstanceState)
|
||||
if (isLoad && !BuildConfig.DEBUG) {
|
||||
AppCenter.start(
|
||||
application,
|
||||
"ae2037d3-9914-4e0c-b02b-f9b2bb2574e5",
|
||||
Analytics::class.java,
|
||||
Crashes::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//检测LSPosed是否激活
|
||||
|
||||
@@ -2,18 +2,24 @@ package com.lt2333.simplicitytools.hooks.apps
|
||||
|
||||
import android.os.Build
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.android.AllowUntrustedTouchesForAll
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.android.DeleteOnPostNotificationForAll
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.android.DisableFlagSecureForAll
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.corepatch.CorePatchMainHook
|
||||
|
||||
object AndroidHooker: YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
//判断Android版本号加载不同的Hooker
|
||||
when (Build.VERSION.SDK_INT) {
|
||||
Build.VERSION_CODES.TIRAMISU -> {
|
||||
Build.VERSION_CODES.TIRAMISU -> { //Android13
|
||||
loadHooker(DisableFlagSecureForAll) //允许截图
|
||||
loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸
|
||||
loadHooker(DeleteOnPostNotificationForAll) //上层显示
|
||||
}
|
||||
|
||||
Build.VERSION_CODES.S -> {
|
||||
Build.VERSION_CODES.S -> { //Android12
|
||||
loadHooker(DisableFlagSecureForAll) //允许截图
|
||||
loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸
|
||||
loadHooker(DeleteOnPostNotificationForAll) //上层显示
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,17 @@ package com.lt2333.simplicitytools.hooks.apps
|
||||
|
||||
import android.os.Build
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.miuihome.ShortcutAddSmallWindowForAll
|
||||
|
||||
object MiuiHomeHooker: YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
when (Build.VERSION.SDK_INT) {
|
||||
Build.VERSION_CODES.TIRAMISU -> {
|
||||
loadHooker(ShortcutAddSmallWindowForAll) //快捷方式添加小窗
|
||||
}
|
||||
|
||||
Build.VERSION_CODES.S -> {
|
||||
loadHooker(ShortcutAddSmallWindowForAll) //快捷方式添加小窗
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,45 @@ package com.lt2333.simplicitytools.hooks.apps
|
||||
|
||||
import android.os.Build
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.hooks.rules.all.android.DisableFlagSecureForAll
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideBatteryIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideHDIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideMobileActivityIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideMobileTypeIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideSimIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideStatusBarIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideStatusBarNetworkSpeedSecondForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.HideWifiActivityIconForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.MaximumNumberOfNotificationIconsForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.NewControlCenterWeatherForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.NotificationWeatherForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.OldNotificationWeatherForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.RemoveLockScreenCameraForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.RemoveTheLeftSideOfTheLockScreenForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.StatusBarLayoutForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.StatusBarNetworkSpeedRefreshSpeedForT
|
||||
import com.lt2333.simplicitytools.hooks.rules.t.systemui.StatusBarTimeCustomizationForT
|
||||
|
||||
object SystemUIHooker : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
when (Build.VERSION.SDK_INT) {
|
||||
Build.VERSION_CODES.TIRAMISU -> {
|
||||
loadHooker(HideStatusBarIconForT) //隐藏状态栏图标
|
||||
loadHooker(HideBatteryIconForT) //隐藏电池
|
||||
loadHooker(HideHDIconForT) //隐藏HD图标
|
||||
loadHooker(HideSimIconForT) //隐藏SIM卡图标
|
||||
loadHooker(HideMobileActivityIconForT) //隐藏移动箭头图标
|
||||
loadHooker(HideMobileTypeIconForT) //隐藏移动类型图标
|
||||
loadHooker(HideStatusBarNetworkSpeedSecondForT) //隐藏状态栏网速/s
|
||||
loadHooker(HideWifiActivityIconForT) //隐藏WIFI活动箭头图标
|
||||
loadHooker(MaximumNumberOfNotificationIconsForT) //通知图标上限
|
||||
loadHooker(StatusBarNetworkSpeedRefreshSpeedForT) //状态栏网速秒刷新
|
||||
loadHooker(StatusBarTimeCustomizationForT) //状态栏时钟自定义
|
||||
loadHooker(RemoveTheLeftSideOfTheLockScreenForT) //移除锁屏负一屏功能
|
||||
loadHooker(RemoveLockScreenCameraForT) //移除锁屏相机功能
|
||||
loadHooker(NotificationWeatherForT) //通知面板天气
|
||||
loadHooker(NewControlCenterWeatherForT) //新控制中心天气
|
||||
loadHooker(OldNotificationWeatherForT) //经典通知天气
|
||||
loadHooker(StatusBarLayoutForT) //状态栏布局
|
||||
}
|
||||
|
||||
Build.VERSION_CODES.S -> {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.all.android
|
||||
|
||||
import android.content.Context
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object AllowUntrustedTouchesForAll : YukiBaseHooker() {
|
||||
override fun onHook() = hasEnable("allow_untrusted_touches") {
|
||||
"android.hardware.input.InputManager".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "getBlockUntrustedTouchesMode"
|
||||
param(Context::class.java)
|
||||
}
|
||||
replaceTo(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.all.android
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object DeleteOnPostNotificationForAll: YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.server.wm.AlertWindowNotification".hook {
|
||||
injectMember {
|
||||
method { name = "onPostNotification" }
|
||||
beforeHook {
|
||||
hasEnable("delete_on_post_notification") {
|
||||
this.result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ object DisableFlagSecureForAll : YukiBaseHooker() {
|
||||
method { name = "setSecure" }
|
||||
beforeHook {
|
||||
hasEnable("disable_flag_secure") {
|
||||
this.args[0] = false
|
||||
args[0] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,10 +32,10 @@ object DisableFlagSecureForAll : YukiBaseHooker() {
|
||||
allMembers(MembersType.CONSTRUCTOR)
|
||||
beforeHook {
|
||||
hasEnable("disable_flag_secure") {
|
||||
var flags = this.args[2] as Int
|
||||
var flags = args[2] as Int
|
||||
val secureFlag = 128
|
||||
flags = flags and secureFlag.inv()
|
||||
this.args[2] = flags
|
||||
args[2] = flags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.all.miuihome
|
||||
|
||||
import android.app.AndroidAppHelper
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.field
|
||||
import com.lt2333.simplicitytools.R
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object ShortcutAddSmallWindowForAll : YukiBaseHooker() {
|
||||
override fun onHook() = hasEnable("miuihome_shortcut_add_small_window") {
|
||||
val mViewDarkModeHelper = "com.miui.home.launcher.util.ViewDarkModeHelper".toClass()
|
||||
val mSystemShortcutMenu = "com.miui.home.launcher.shortcuts.SystemShortcutMenu".toClass()
|
||||
val mSystemShortcutMenuItem = "com.miui.home.launcher.shortcuts.SystemShortcutMenuItem".toClass()
|
||||
val mAppShortcutMenu = "com.miui.home.launcher.shortcuts.AppShortcutMenu".toClass()
|
||||
val mShortcutMenuItem = "com.miui.home.launcher.shortcuts.ShortcutMenuItem".toClass()
|
||||
val mAppDetailsShortcutMenuItem = "com.miui.home.launcher.shortcuts.SystemShortcutMenuItem\$AppDetailsShortcutMenuItem".toClass()
|
||||
val mActivityUtilsCompat = "com.miui.launcher.utils.ActivityUtilsCompat".toClass()
|
||||
|
||||
mViewDarkModeHelper.hook {
|
||||
injectMember {
|
||||
method { name = "onConfigurationChanged" }.all()
|
||||
afterHook {
|
||||
mSystemShortcutMenuItem.current {
|
||||
method { name = "createAllSystemShortcutMenuItems" }.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mShortcutMenuItem.hook {
|
||||
injectMember {
|
||||
method { name = "getShortTitle" }
|
||||
afterHook {
|
||||
if (this.result == "应用信息") {
|
||||
this.result = "信息"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mAppDetailsShortcutMenuItem.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "lambda\$getOnClickListener$0"
|
||||
paramCount = 2
|
||||
}
|
||||
beforeHook {
|
||||
val obj = args[0]
|
||||
val view: View = args[1] as View
|
||||
val mShortTitle = obj?.current {
|
||||
method { name = "getShortTitle" }.invoke<CharSequence>()
|
||||
}
|
||||
|
||||
if (mShortTitle == moduleAppResources.getString(R.string.miuihome_shortcut_add_small_window_title)) {
|
||||
this.result = null
|
||||
val intent = Intent()
|
||||
val mComponentName = obj.current {
|
||||
method { name = "getComponentName" }.call()
|
||||
} as ComponentName
|
||||
intent.action = "android.intent.action.MAIN"
|
||||
intent.addCategory("android.intent.category.LAUNCHER")
|
||||
intent.component = mComponentName
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
val callStaticMethod = mActivityUtilsCompat.current {
|
||||
method {
|
||||
name = "makeFreeformActivityOptions"
|
||||
paramCount = 2
|
||||
}.call(
|
||||
view.context, mComponentName.packageName
|
||||
)
|
||||
}
|
||||
if (callStaticMethod != null) {
|
||||
view.context.startActivity(intent, callStaticMethod.current {
|
||||
method { name = "toBundle" }.call()
|
||||
} as Bundle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mSystemShortcutMenu.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "getMaxShortcutItemCount"
|
||||
}.all()
|
||||
afterHook {
|
||||
this.result = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
mAppShortcutMenu.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "getMaxShortcutItemCount"
|
||||
}.all()
|
||||
afterHook {
|
||||
this.result = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
mSystemShortcutMenuItem.hook {
|
||||
injectMember {
|
||||
method { name = "createAllSystemShortcutMenuItems" }.all()
|
||||
afterHook {
|
||||
val isDarkMode =
|
||||
AndroidAppHelper.currentApplication().applicationContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||
val mAllSystemShortcutMenuItems = mSystemShortcutMenuItem.field {
|
||||
name = "sAllSystemShortcutMenuItems"
|
||||
}.get().cast<Collection<Any>>()
|
||||
val mSmallWindowInstance = mAppDetailsShortcutMenuItem.newInstance()
|
||||
mSmallWindowInstance.current {
|
||||
method {
|
||||
name = "setShortTitle"
|
||||
}.call(moduleAppResources.getString(R.string.miuihome_shortcut_add_small_window_title))
|
||||
}
|
||||
mSmallWindowInstance.current {
|
||||
method {
|
||||
name = "setIconDrawable"
|
||||
}.call(if (isDarkMode) moduleAppResources.getDrawable(R.drawable.ic_small_window_dark) else moduleAppResources.getDrawable(R.drawable.ic_small_window_light))
|
||||
}
|
||||
val sAllSystemShortcutMenuItems = ArrayList<Any>()
|
||||
sAllSystemShortcutMenuItems.add(mSmallWindowInstance)
|
||||
mAllSystemShortcutMenuItems?.let { sAllSystemShortcutMenuItems.addAll(it) }
|
||||
mSystemShortcutMenuItem.field { name = "sAllSystemShortcutMenuItems" }.get().set(sAllSystemShortcutMenuItems)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideBatteryIconForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
|
||||
"com.android.systemui.statusbar.views.MiuiBatteryMeterView".hook {
|
||||
injectMember {
|
||||
method { name = "updateResources" }
|
||||
afterHook {
|
||||
//隐藏电池图标
|
||||
hasEnable("hide_battery_icon") {
|
||||
//从当前实例中,获取名为mBatteryStyle的Field,并转换成ImageView类型,操作可见度
|
||||
instance.current().field { name = "mBatteryStyle" }.cast<ImageView>()?.visibility = View.GONE
|
||||
if (instance.current().field { name = "mBatteryStyle" }.int() == 1) {
|
||||
instance.current().field { name = "mBatteryDigitalView" }.cast<FrameLayout>()?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
//隐藏电池内的百分比
|
||||
hasEnable("hide_battery_percentage_icon") {
|
||||
instance.current().field { name = "mBatteryPercentMarkView" }.cast<TextView>()?.textSize=0F
|
||||
}
|
||||
|
||||
"com.android.systemui.statusbar.views.MiuiBatteryMeterView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateChargeAndText"
|
||||
}
|
||||
afterHook {
|
||||
//隐藏电池充电图标
|
||||
hasEnable("hide_battery_charging_icon") {
|
||||
instance.current().field { name = "mBatteryChargingInView" }.cast<ImageView>()?.visibility = View.GONE
|
||||
instance.current().field { name = "mBatteryChargingView" }.cast<ImageView>()?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideHDIconForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.StatusBarMobileView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "initViewState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
hasEnable("hide_new_hd_icon") {
|
||||
"com.android.systemui.statusbar.policy.HDController".hook {
|
||||
injectMember {
|
||||
method { name = "update" }
|
||||
beforeHook {
|
||||
this.result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun hide(it: HookParam) {
|
||||
hasEnable("hide_big_hd_icon") {
|
||||
//从当前实例中,获取名为mVolte的Field,并转换成ImageView类型,操作可见度
|
||||
it.instance.current().field {name = "mVolte" }.cast<ImageView>()?.visibility = View.GONE
|
||||
}
|
||||
hasEnable("hide_small_hd_icon") {
|
||||
it.instance.current().field {name = "mSmallHd" }.cast<ImageView>()?.visibility = View.GONE
|
||||
}
|
||||
hasEnable("hide_hd_no_service_icon") {
|
||||
it.instance.current().field {name = "mVolteNoService" }.cast<ImageView>()?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideMobileActivityIconForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.StatusBarMobileView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "initViewState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.statusbar.StatusBarMobileView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide(it: HookParam) {
|
||||
hasEnable("hide_mobile_activity_icon") {
|
||||
it.instance.current().field { name = "mLeftInOut" }.cast<ImageView>()?.visibility = View.GONE
|
||||
it.instance.current().field { name = "mRightInOut" }.cast<ImageView>()?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideMobileTypeIconForT : YukiBaseHooker() {
|
||||
|
||||
private val isBigType = XSPUtils.getBoolean("big_mobile_type_icon", false)
|
||||
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.StatusBarMobileView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "initViewState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hideMobileTypeIcon(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.statusbar.StatusBarMobileView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hideMobileTypeIcon(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideMobileTypeIcon(it: HookParam) {
|
||||
hasEnable("hide_mobile_type_icon") {
|
||||
if (isBigType) {
|
||||
it.instance.current().field { name = "mMobileType" }.cast<ImageView>()?.visibility = View.GONE
|
||||
it.instance.current().field { name = "mMobileTypeImage" }.cast<ImageView>()?.visibility = View.GONE
|
||||
it.instance.current().field { name = "mMobileTypeSingle" }.cast<ImageView>()?.visibility = View.GONE
|
||||
} else {
|
||||
it.instance.current().field { name = "mMobileType" }.cast<ImageView>()?.visibility = View.INVISIBLE
|
||||
it.instance.current().field { name = "mMobileTypeImage" }.cast<ImageView>()?.visibility = View.INVISIBLE
|
||||
it.instance.current().field { name = "mMobileTypeSingle" }.cast<ImageView>()?.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideSimIconForT:YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.phone.StatusBarSignalPolicy".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "hasCorrectSubs"
|
||||
param(MutableList::class.java)
|
||||
}
|
||||
beforeHook {
|
||||
val list = args[0] as MutableList<*>
|
||||
val size = list.size
|
||||
hasEnable("hide_sim_two_icon", extraCondition = { size == 2 }) {
|
||||
list.removeAt(1)
|
||||
}
|
||||
hasEnable("hide_sim_one_icon", extraCondition = { size >= 1 }) {
|
||||
list.removeAt(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideStatusBarIconForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.phone.StatusBarIconControllerImpl".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "setIconVisibility"
|
||||
paramCount = 2
|
||||
}
|
||||
beforeHook {
|
||||
hideIcon(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "setIconVisibility"
|
||||
paramCount = 2
|
||||
}
|
||||
beforeHook {
|
||||
hideIcon(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun hideIcon(it: HookParam) {
|
||||
//Log.d("图标名字", "handleLoadPackage: " + it.args[0])
|
||||
when (it.args[0] as String) {
|
||||
//隐藏蓝牙
|
||||
"bluetooth" -> hasEnable("hide_bluetooth_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏蓝牙电量
|
||||
"bluetooth_handsfree_battery" -> hasEnable("hide_bluetooth_battery_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏勿扰
|
||||
"zen" -> hasEnable("hide_zen_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏声音
|
||||
"volume" -> hasEnable("hide_volume_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏WIFI
|
||||
"wifi" -> hasEnable("hide_wifi_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏WIFI辅助
|
||||
"slave_wifi" -> hasEnable("hide_slave_wifi_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏飞行模式
|
||||
"airplane" -> hasEnable("hide_airplane_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏闹钟
|
||||
"alarm_clock" -> hasEnable("hide_alarm_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏定位
|
||||
"location" -> hasEnable("hide_gps_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏热点
|
||||
"hotspot" -> hasEnable("hide_hotspot_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏耳机
|
||||
"headset" -> hasEnable("hide_headset_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏VPN
|
||||
"vpn" -> hasEnable("hide_vpn_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏无SIM卡
|
||||
"no_sim" -> hasEnable("hide_no_sim_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
//隐藏NFC图标
|
||||
"nfc" -> hasEnable("hide_nfc_icon") {
|
||||
it.args[1] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideStatusBarNetworkSpeedSecondForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.views.NetworkSpeedView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "setNetworkSpeed"
|
||||
paramCount = 1
|
||||
}
|
||||
beforeHook {
|
||||
hasEnable("hide_status_bar_network_speed_second") {
|
||||
if (args[0] != null) {
|
||||
val mText = (args[0] as String)
|
||||
.replace("/", "")
|
||||
.replace("s", "")
|
||||
.replace("\'", "")
|
||||
.replace("วิ", "")
|
||||
args[0] = mText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object HideWifiActivityIconForT: YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.StatusBarWifiView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "initViewState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
"com.android.systemui.statusbar.StatusBarWifiView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateState"
|
||||
paramCount = 1
|
||||
}
|
||||
afterHook {
|
||||
hide(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun hide(it: HookParam) {
|
||||
//隐藏WIFI箭头
|
||||
hasEnable("hide_wifi_activity_icon") {
|
||||
it.instance.current().field { name = "mWifiActivityView" }.cast<ImageView>()?.visibility = View.INVISIBLE
|
||||
}
|
||||
//隐藏WIFI标准图标
|
||||
hasEnable("hide_wifi_standard_icon") {
|
||||
it.instance.current().field { name = "mWifiStandardView" }.cast<TextView>()?.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
|
||||
object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
val icons = XSPUtils.getInt("maximum_number_of_notification_icons", 3)
|
||||
val dots = XSPUtils.getInt("maximum_number_of_notification_dots", 3)
|
||||
"com.android.systemui.statusbar.phone.NotificationIconContainer".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "miuiShowNotificationIcons"
|
||||
paramCount = 1
|
||||
}
|
||||
replaceUnit {
|
||||
if (args[0] as Boolean) {
|
||||
instance.current().field { name = "MAX_DOTS" }.set(dots)
|
||||
instance.current().field { name = "MAX_STATIC_ICONS" }.set(icons)
|
||||
instance.current().field { name = "MAX_ICONS_ON_LOCKSCREEN" }.set(icons)
|
||||
} else {
|
||||
instance.current().field { name = "MAX_DOTS" }.set(0)
|
||||
instance.current().field { name = "MAX_STATIC_ICONS" }.set(0)
|
||||
instance.current().field { name = "MAX_ICONS_ON_LOCKSCREEN" }.set(0)
|
||||
}
|
||||
instance.current().method { name = "updateState" }.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.widget.TextView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
import com.lt2333.simplicitytools.views.WeatherData
|
||||
|
||||
object NewControlCenterWeatherForT : YukiBaseHooker() {
|
||||
override fun onHook() = hasEnable("control_center_weather") {
|
||||
lateinit var weather: WeatherData
|
||||
var clockId: Int = -2
|
||||
val isDisplayCity = XSPUtils.getBoolean("notification_weather_city", false)
|
||||
|
||||
"com.android.systemui.controlcenter.phone.widget.ControlCenterDateView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onDetachedFromWindow"
|
||||
superClass(true)
|
||||
}
|
||||
beforeHook {
|
||||
if (instance<TextView>().id == clockId) {
|
||||
weather.onDetachedFromWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.controlcenter.phone.widget.ControlCenterDateView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "setText"
|
||||
superClass(true)
|
||||
}
|
||||
beforeHook {
|
||||
val time = args[0]?.toString()
|
||||
val view = instance<TextView>()
|
||||
if (view.id == clockId && time != null) {
|
||||
args[0] = "${weather.weatherData}$time"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.shared.plugins.PluginInstance\$Factory".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "getClassLoader"
|
||||
}
|
||||
afterHook {
|
||||
val appInfo = args[0] as ApplicationInfo
|
||||
val classLoader = this.result as ClassLoader
|
||||
if (appInfo.packageName == "miui.systemui.plugin") {
|
||||
"miui.systemui.controlcenter.windowview.MainPanelHeaderController".hook {
|
||||
injectMember {
|
||||
appClassLoader = classLoader
|
||||
method {
|
||||
name = "addClockViews"
|
||||
}
|
||||
afterHook {
|
||||
val dateView = instance.current().field { name = "dateView" }.cast<TextView>()
|
||||
if (dateView != null) {
|
||||
clockId = dateView.id
|
||||
}
|
||||
weather = WeatherData(dateView?.context, isDisplayCity)
|
||||
weather.callBacks = {
|
||||
dateView?.current {
|
||||
method {
|
||||
name = "updateTime"
|
||||
superClass(true)
|
||||
}.call()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onHookClassNotFoundFailure { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import cn.fkj233.ui.activity.dp2px
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.buildOf
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.SystemProperties
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
import com.lt2333.simplicitytools.views.WeatherView
|
||||
|
||||
object NotificationWeatherForT : YukiBaseHooker() {
|
||||
override fun onHook() = hasEnable("notification_weather") {
|
||||
var mWeatherView: TextView? = null
|
||||
var mConstraintLayout: ConstraintLayout? = null
|
||||
val isDisplayCity = XSPUtils.getBoolean("notification_weather_city", false)
|
||||
"com.android.systemui.qs.MiuiNotificationHeaderView".hook {
|
||||
injectMember {
|
||||
method { name = "onFinishInflate" }
|
||||
afterHook {
|
||||
val viewGroup = instance<ViewGroup>()
|
||||
val context = viewGroup.context
|
||||
|
||||
// MIUI编译时间大于 2022-03-12 00:00:00 且为内测版
|
||||
if (SystemProperties[context, "ro.build.date.utc"].toInt() >= 1647014400 &&
|
||||
!SystemProperties[context, "ro.build.version.incremental"].endsWith("XM")
|
||||
) {
|
||||
//获取原组件
|
||||
val bigTimeId =
|
||||
context.resources.getIdentifier("big_time", "id", context.packageName)
|
||||
val bigTime: TextView = viewGroup.findViewById(bigTimeId)
|
||||
|
||||
val dateTimeId =
|
||||
context.resources.getIdentifier("date_time", "id", context.packageName)
|
||||
val dateTime: TextView = viewGroup.findViewById(dateTimeId)
|
||||
|
||||
//创建新布局
|
||||
val mConstraintLayoutLp = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
).also {
|
||||
it.topMargin = context.resources.getDimensionPixelSize(
|
||||
context.resources.getIdentifier(
|
||||
"qs_control_header_tiles_margin_top",
|
||||
"dimen",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
mConstraintLayout =
|
||||
ConstraintLayout(context).also { it.layoutParams = mConstraintLayoutLp }
|
||||
|
||||
(bigTime.parent as ViewGroup).addView(mConstraintLayout, 0)
|
||||
|
||||
|
||||
//从原布局中删除组件
|
||||
(bigTime.parent as ViewGroup).removeView(bigTime)
|
||||
(dateTime.parent as ViewGroup).removeView(dateTime)
|
||||
|
||||
|
||||
//添加组件至新布局
|
||||
mConstraintLayout!!.addView(bigTime)
|
||||
mConstraintLayout!!.addView(dateTime)
|
||||
|
||||
//组件属性
|
||||
|
||||
val dateTimeLp = ConstraintLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT,
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
).also {
|
||||
it.startToEnd = bigTimeId
|
||||
it.bottomToBottom = 0
|
||||
it.marginStart = context.resources.getDimensionPixelSize(
|
||||
context.resources.getIdentifier(
|
||||
"notification_panel_time_date_space",
|
||||
"dimen",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
it.bottomMargin = dp2px(context, 5f)
|
||||
}
|
||||
dateTime.layoutParams = dateTimeLp
|
||||
|
||||
|
||||
//创建天气组件
|
||||
mWeatherView = WeatherView(context, isDisplayCity).apply {
|
||||
setTextAppearance(
|
||||
context.resources.getIdentifier(
|
||||
"TextAppearance.QSControl.Date",
|
||||
"style",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
mConstraintLayout!!.addView(mWeatherView)
|
||||
|
||||
val mweatherviewLp = ConstraintLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT,
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
).also {
|
||||
it.startToEnd = bigTimeId
|
||||
it.bottomToTop = dateTimeId
|
||||
it.marginStart = context.resources.getDimensionPixelSize(
|
||||
context.resources.getIdentifier(
|
||||
"notification_panel_time_date_space",
|
||||
"dimen",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
(mWeatherView as WeatherView).layoutParams = mweatherviewLp
|
||||
|
||||
} else {
|
||||
// 通过YukiHook的构造方法创建新实例,指定类型 ViewGroup.MarginLayoutParams
|
||||
val layoutParam = "androidx.constraintlayout.widget.ConstraintLayout\$LayoutParams".toClass()
|
||||
.buildOf<ViewGroup.MarginLayoutParams>(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
) {
|
||||
paramCount = 2
|
||||
}
|
||||
|
||||
|
||||
layoutParam?.current()?.field { name = "bottomToTop" }
|
||||
?.set(context.resources.getIdentifier("date_time", "id", context.packageName))
|
||||
layoutParam?.current()?.field { name = "startToEnd" }
|
||||
?.set(context.resources.getIdentifier("big_time", "id", context.packageName))
|
||||
|
||||
layoutParam?.marginStart = context.resources.getDimensionPixelSize(
|
||||
context.resources.getIdentifier(
|
||||
"notification_panel_time_date_space",
|
||||
"dimen",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
mWeatherView = WeatherView(context, isDisplayCity).apply {
|
||||
setTextAppearance(
|
||||
context.resources.getIdentifier(
|
||||
"TextAppearance.QSControl.Date",
|
||||
"style",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
layoutParams = layoutParam
|
||||
}
|
||||
viewGroup.addView(mWeatherView)
|
||||
}
|
||||
|
||||
(mWeatherView as WeatherView).setOnClickListener {
|
||||
try {
|
||||
val intent = Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
component = ComponentName(
|
||||
"com.miui.weather2",
|
||||
"com.miui.weather2.ActivityWeatherMain"
|
||||
)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, "启动失败", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method { name = "updateLayout" }
|
||||
afterHook {
|
||||
val viewGroup = instance<ViewGroup>()
|
||||
val context = viewGroup.context
|
||||
val mOrientation = viewGroup.current().field { name = "mOrientation" }.int()
|
||||
// MIUI编译时间大于 2022-03-12 00:00:00 且为内测版
|
||||
if (SystemProperties[context, "ro.build.date.utc"].toInt() >= 1647014400 && !SystemProperties[context, "ro.build.version.incremental"].endsWith(
|
||||
"DEV"
|
||||
) && !SystemProperties[context, "ro.build.version.incremental"].endsWith("XM")
|
||||
) {
|
||||
if (mOrientation == 1) {
|
||||
mConstraintLayout!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
mConstraintLayout!!.visibility = View.GONE
|
||||
}
|
||||
} else {
|
||||
if (mOrientation == 1) {
|
||||
mWeatherView!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
mWeatherView!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
import com.lt2333.simplicitytools.views.WeatherView
|
||||
|
||||
object OldNotificationWeatherForT : YukiBaseHooker() {
|
||||
override fun onHook() = hasEnable("notification_weather") {
|
||||
var mWeatherView: TextView? = null
|
||||
val isDisplayCity = XSPUtils.getBoolean("notification_weather_city", false)
|
||||
"com.android.systemui.qs.MiuiQSHeaderView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onFinishInflate"
|
||||
}
|
||||
afterHook {
|
||||
val viewGroup = instance<ViewGroup>()
|
||||
val context = viewGroup.context
|
||||
|
||||
mWeatherView = WeatherView(context, isDisplayCity).apply {
|
||||
setTextAppearance(
|
||||
context.resources.getIdentifier(
|
||||
"TextAppearance.StatusBar.Expanded.Clock.QuickSettingDate",
|
||||
"style",
|
||||
context.packageName
|
||||
)
|
||||
)
|
||||
}
|
||||
viewGroup.addView(mWeatherView)
|
||||
(mWeatherView as WeatherView).setOnClickListener {
|
||||
try {
|
||||
val intent = Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
component = ComponentName(
|
||||
"com.miui.weather2",
|
||||
"com.miui.weather2.ActivityWeatherMain"
|
||||
)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, "启动失败,可能是不支持", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"com.android.systemui.qs.MiuiQSHeaderView".hook {
|
||||
injectMember {
|
||||
method { name = "updateLayout" }
|
||||
afterHook {
|
||||
val mOrientation = instance.current().field { name = "mOrientation" }.int()
|
||||
if (mOrientation == 1) {
|
||||
mWeatherView!!.visibility = View.VISIBLE
|
||||
} else {
|
||||
mWeatherView!!.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object RemoveLockScreenCameraForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.phone.KeyguardBottomAreaView".hook {
|
||||
injectMember {
|
||||
method { name = "onFinishInflate" }
|
||||
afterHook {
|
||||
hasEnable("remove_lock_screen_camera") {
|
||||
instance.current().field { name = "mRightAffordanceViewLayout" }
|
||||
.cast<LinearLayout>()?.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object RemoveTheLeftSideOfTheLockScreenForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.keyguard.negative.MiuiKeyguardMoveLeftViewContainer".hook {
|
||||
injectMember {
|
||||
method { name = "inflateLeftView" }
|
||||
beforeHook {
|
||||
hasEnable("remove_the_left_side_of_the_lock_screen") {
|
||||
resultNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import cn.fkj233.ui.activity.dp2px
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object StatusBarLayoutForT : YukiBaseHooker() {
|
||||
|
||||
private val getMode = XSPUtils.getInt("status_bar_layout_mode", 0)
|
||||
private val isCompatibilityMode = XSPUtils.getBoolean("layout_compatibility_mode", false)
|
||||
|
||||
private var statusBarLeft = 0
|
||||
private var statusBarTop = 0
|
||||
private var statusBarRight = 0
|
||||
private var statusBarBottom = 0
|
||||
|
||||
override fun onHook() {
|
||||
var mLeftLayout: LinearLayout? = null
|
||||
var mRightLayout: LinearLayout? = null
|
||||
var mCenterLayout: LinearLayout?
|
||||
var statusBar: ViewGroup? = null
|
||||
|
||||
//判断屏幕状态更新布局 mode: 1正常布局 2居中布局
|
||||
fun updateLayout(context: Context, mode: Int) {
|
||||
runCatching {
|
||||
when (mode) {
|
||||
1 -> {
|
||||
val mConfiguration: Configuration = context.resources.configuration
|
||||
if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { //横屏
|
||||
statusBar!!.setPadding(statusBarLeft, statusBarTop, statusBarRight, statusBarBottom)
|
||||
}
|
||||
}
|
||||
|
||||
2 -> {
|
||||
val mConfiguration: Configuration = context.resources.configuration
|
||||
if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { //横屏
|
||||
mLeftLayout!!.setPadding(statusBarLeft, 0, 0, 0)
|
||||
mRightLayout!!.setPadding(0, 0, statusBarRight, 0)
|
||||
statusBar!!.setPadding(0, statusBarTop, 0, statusBarBottom)
|
||||
} else { //竖屏
|
||||
mLeftLayout!!.setPadding(0, 0, 0, 0)
|
||||
mRightLayout!!.setPadding(0, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.getOrNull()
|
||||
|
||||
}
|
||||
|
||||
//判断是否开启挖孔兼容模式
|
||||
if (isCompatibilityMode) {
|
||||
"com.android.systemui.ScreenDecorations".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "boundsFromDirection"
|
||||
paramCount = 3
|
||||
}
|
||||
beforeHook {
|
||||
args[1] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//修改对应布局
|
||||
when (getMode) {
|
||||
//默认
|
||||
0 -> {
|
||||
"com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onViewCreated"
|
||||
paramCount = 2
|
||||
}
|
||||
afterHook {
|
||||
val miuiPhoneStatusBarView =args(0).cast<ViewGroup>()!!
|
||||
val context: Context = miuiPhoneStatusBarView.context
|
||||
val res: Resources = miuiPhoneStatusBarView.resources
|
||||
val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui")
|
||||
statusBar = miuiPhoneStatusBarView.findViewById(statusBarId)
|
||||
if (statusBar == null) return@afterHook
|
||||
|
||||
statusBarLeft = statusBar!!.paddingLeft
|
||||
statusBarTop = statusBar!!.paddingTop
|
||||
statusBarRight = statusBar!!.paddingRight
|
||||
statusBarBottom = statusBar!!.paddingBottom
|
||||
|
||||
if (isCompatibilityMode) {
|
||||
val customLeftMargin = XSPUtils.getInt("status_bar_left_margin", 0)
|
||||
if (customLeftMargin != 0) {
|
||||
statusBarLeft = customLeftMargin
|
||||
}
|
||||
|
||||
val customRightMargin = XSPUtils.getInt("status_bar_right_margin", 0)
|
||||
if (customRightMargin != 0) {
|
||||
statusBarRight = customRightMargin
|
||||
}
|
||||
updateLayout(context, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//兼容模式
|
||||
"com.android.systemui.statusbar.phone.PhoneStatusBarView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateLayoutForCutout"
|
||||
}
|
||||
afterHook {
|
||||
if (isCompatibilityMode) {
|
||||
val context = instance<ViewGroup>().context
|
||||
updateLayout(context, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//时钟居中
|
||||
1 -> {
|
||||
"com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onViewCreated"
|
||||
paramCount = 2
|
||||
}
|
||||
afterHook {
|
||||
val miuiPhoneStatusBarView = args(0).cast<ViewGroup>()!!
|
||||
val context: Context = miuiPhoneStatusBarView.context
|
||||
val res: Resources = miuiPhoneStatusBarView.resources
|
||||
val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui")
|
||||
val statusBarContentsId: Int = res.getIdentifier(
|
||||
"status_bar_contents", "id", "com.android.systemui"
|
||||
)
|
||||
val systemIconAreaId: Int = res.getIdentifier("system_icon_area", "id", "com.android.systemui")
|
||||
val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui")
|
||||
val phoneStatusBarLeftContainerId: Int = res.getIdentifier(
|
||||
"phone_status_bar_left_container", "id", "com.android.systemui"
|
||||
)
|
||||
val notificationIconAreaInnerId: Int = res.getIdentifier(
|
||||
"notification_icon_area_inner", "id", "com.android.systemui"
|
||||
)
|
||||
statusBar = miuiPhoneStatusBarView.findViewById(statusBarId)
|
||||
val statusBarContents: ViewGroup = miuiPhoneStatusBarView.findViewById(statusBarContentsId)
|
||||
if (statusBar == null) return@afterHook
|
||||
val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId)
|
||||
val phoneStatusBarLeftContainer: ViewGroup = miuiPhoneStatusBarView.findViewById(
|
||||
phoneStatusBarLeftContainerId
|
||||
)
|
||||
val notificationIconAreaInner: ViewGroup = miuiPhoneStatusBarView.findViewById(
|
||||
notificationIconAreaInnerId
|
||||
)
|
||||
val systemIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconAreaId)
|
||||
|
||||
(clock.parent as ViewGroup).removeView(clock)
|
||||
(phoneStatusBarLeftContainer.parent as ViewGroup).removeView(
|
||||
phoneStatusBarLeftContainer
|
||||
)
|
||||
(notificationIconAreaInner.parent as ViewGroup).removeView(
|
||||
notificationIconAreaInner
|
||||
)
|
||||
(systemIconArea.parent as ViewGroup).removeView(systemIconArea)
|
||||
|
||||
val mConstraintLayout = ConstraintLayout(context).also {
|
||||
it.layoutParams = ConstraintLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
|
||||
mConstraintLayout.addView(notificationIconAreaInner)
|
||||
|
||||
val fullscreenNotificationIconAreaLp = LinearLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
|
||||
notificationIconAreaInner.layoutParams = fullscreenNotificationIconAreaLp
|
||||
|
||||
//增加一个左对齐布局
|
||||
mLeftLayout = LinearLayout(context)
|
||||
val leftLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f
|
||||
)
|
||||
mLeftLayout!!.layoutParams = leftLp
|
||||
mLeftLayout!!.gravity = Gravity.START or Gravity.CENTER_VERTICAL
|
||||
|
||||
//增加一个居中布局
|
||||
mCenterLayout = LinearLayout(context)
|
||||
val centerLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
mCenterLayout!!.layoutParams = centerLp
|
||||
mCenterLayout!!.gravity = Gravity.CENTER or Gravity.CENTER_VERTICAL
|
||||
mRightLayout = LinearLayout(context)
|
||||
val rightLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f
|
||||
)
|
||||
mRightLayout!!.layoutParams = rightLp
|
||||
mRightLayout!!.gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
||||
mLeftLayout!!.addView(phoneStatusBarLeftContainer)
|
||||
mLeftLayout!!.addView(mConstraintLayout)
|
||||
|
||||
mCenterLayout!!.addView(clock)
|
||||
mRightLayout!!.addView(systemIconArea)
|
||||
statusBarContents.addView(mLeftLayout, 0)
|
||||
statusBarContents.addView(mCenterLayout)
|
||||
statusBarContents.addView(mRightLayout)
|
||||
|
||||
statusBarLeft = statusBar!!.paddingLeft
|
||||
statusBarTop = statusBar!!.paddingTop
|
||||
statusBarRight = statusBar!!.paddingRight
|
||||
statusBarBottom = statusBar!!.paddingBottom
|
||||
|
||||
|
||||
if (isCompatibilityMode) {
|
||||
val customLeftMargin = XSPUtils.getInt("status_bar_left_margin", 0)
|
||||
if (customLeftMargin != 0) {
|
||||
statusBarLeft = customLeftMargin
|
||||
}
|
||||
|
||||
val customRightMargin = XSPUtils.getInt("status_bar_right_margin", 0)
|
||||
if (customRightMargin != 0) {
|
||||
statusBarRight = customRightMargin
|
||||
}
|
||||
updateLayout(context, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//兼容模式
|
||||
"com.android.systemui.statusbar.phone.PhoneStatusBarView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateLayoutForCutout"
|
||||
}
|
||||
afterHook {
|
||||
hasEnable("layout_compatibility_mode") {
|
||||
val context = instance<ViewGroup>().context
|
||||
updateLayout(context, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//时钟居右
|
||||
2 -> {
|
||||
"com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onViewCreated"
|
||||
paramCount = 2
|
||||
}
|
||||
afterHook {
|
||||
val miuiPhoneStatusBarView = args(0).cast<ViewGroup>()!!
|
||||
val context: Context = miuiPhoneStatusBarView.context
|
||||
val res: Resources = miuiPhoneStatusBarView.resources
|
||||
|
||||
//组件ID
|
||||
val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui")
|
||||
val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui")
|
||||
val batteryId: Int = res.getIdentifier("battery", "id", "com.android.systemui")
|
||||
|
||||
//查找组件
|
||||
statusBar = miuiPhoneStatusBarView.findViewById(statusBarId)
|
||||
if (statusBar == null) return@afterHook
|
||||
val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId)
|
||||
val battery: ViewGroup = miuiPhoneStatusBarView.findViewById(batteryId)
|
||||
|
||||
//新建布局
|
||||
val rightLp = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
).also {
|
||||
it.marginStart = dp2px(context, 5f)
|
||||
}
|
||||
mRightLayout = LinearLayout(context).also {
|
||||
it.layoutParams = rightLp
|
||||
}
|
||||
|
||||
//添加布局与组件
|
||||
battery.addView(mRightLayout)
|
||||
(clock.parent as ViewGroup).removeView(clock)
|
||||
mRightLayout!!.addView(clock)
|
||||
|
||||
|
||||
statusBarLeft = statusBar!!.paddingLeft
|
||||
statusBarTop = statusBar!!.paddingTop
|
||||
statusBarRight = statusBar!!.paddingRight
|
||||
statusBarBottom = statusBar!!.paddingBottom
|
||||
|
||||
|
||||
if (isCompatibilityMode) {
|
||||
val customLeftMargin = XSPUtils.getInt("status_bar_left_margin", 0)
|
||||
if (customLeftMargin != 0) {
|
||||
statusBarLeft = customLeftMargin
|
||||
}
|
||||
|
||||
val customRightMargin = XSPUtils.getInt("status_bar_right_margin", 0)
|
||||
if (customRightMargin != 0) {
|
||||
statusBarRight = customRightMargin
|
||||
}
|
||||
updateLayout(context, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//兼容模式
|
||||
"com.android.systemui.statusbar.phone.PhoneStatusBarView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateLayoutForCutout"
|
||||
}
|
||||
afterHook {
|
||||
if (isCompatibilityMode) {
|
||||
val context = instance<ViewGroup>().context
|
||||
updateLayout(context, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//时钟居中+图标居左
|
||||
3 -> {
|
||||
"com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onViewCreated"
|
||||
paramCount = 2
|
||||
}
|
||||
afterHook {
|
||||
val miuiPhoneStatusBarView = args(0).cast<ViewGroup>()!!
|
||||
val context: Context = miuiPhoneStatusBarView.context
|
||||
val res: Resources = miuiPhoneStatusBarView.resources
|
||||
val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui")
|
||||
val statusBarContentsId: Int = res.getIdentifier(
|
||||
"status_bar_contents", "id", "com.android.systemui"
|
||||
)
|
||||
val systemIconAreaId: Int = res.getIdentifier("system_icon_area", "id", "com.android.systemui")
|
||||
val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui")
|
||||
val phoneStatusBarLeftContainerId: Int = res.getIdentifier(
|
||||
"phone_status_bar_left_container", "id", "com.android.systemui"
|
||||
)
|
||||
val fullscreenNotificationIconAreaId: Int = res.getIdentifier(
|
||||
"fullscreen_notification_icon_area", "id", "com.android.systemui"
|
||||
)
|
||||
val statusIconsId: Int = res.getIdentifier(
|
||||
"statusIcons", "id", "com.android.systemui"
|
||||
)
|
||||
val systemIconsId: Int = res.getIdentifier(
|
||||
"system_icons", "id", "com.android.systemui"
|
||||
)
|
||||
val batteryId: Int = res.getIdentifier(
|
||||
"battery", "id", "com.android.systemui"
|
||||
)
|
||||
|
||||
statusBar = miuiPhoneStatusBarView.findViewById(statusBarId)
|
||||
val statusBarContents: ViewGroup = miuiPhoneStatusBarView.findViewById(statusBarContentsId)
|
||||
if (statusBar == null) return@afterHook
|
||||
val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId)
|
||||
val phoneStatusBarLeftContainer: ViewGroup = miuiPhoneStatusBarView.findViewById(
|
||||
phoneStatusBarLeftContainerId
|
||||
)
|
||||
val fullscreenNotificationIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById(
|
||||
fullscreenNotificationIconAreaId
|
||||
)
|
||||
val systemIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconAreaId)
|
||||
val statusIcons: ViewGroup = miuiPhoneStatusBarView.findViewById(statusIconsId)
|
||||
val systemIcons: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconsId)
|
||||
val battery: ViewGroup = miuiPhoneStatusBarView.findViewById(batteryId)
|
||||
|
||||
(clock.parent as ViewGroup).removeView(clock)
|
||||
(phoneStatusBarLeftContainer.parent as ViewGroup).removeView(
|
||||
phoneStatusBarLeftContainer
|
||||
)
|
||||
(systemIconArea.parent as ViewGroup).removeView(systemIconArea)
|
||||
(statusIcons.parent as ViewGroup).removeView(statusIcons)
|
||||
(systemIcons.parent as ViewGroup).removeView(systemIcons)
|
||||
(battery.parent as ViewGroup).removeView(battery)
|
||||
(fullscreenNotificationIconArea.parent as ViewGroup).removeView(
|
||||
fullscreenNotificationIconArea
|
||||
)
|
||||
|
||||
val mConstraintLayout = ConstraintLayout(context).also {
|
||||
it.layoutParams = ConstraintLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
}
|
||||
|
||||
mConstraintLayout.addView(fullscreenNotificationIconArea)
|
||||
mConstraintLayout.addView(battery)
|
||||
|
||||
|
||||
battery.layoutParams = ConstraintLayout.LayoutParams(
|
||||
ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
).also {
|
||||
it.endToEnd = 0
|
||||
}
|
||||
|
||||
|
||||
fullscreenNotificationIconArea.layoutParams = ConstraintLayout.LayoutParams(
|
||||
0, ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
).also {
|
||||
it.startToEnd = batteryId
|
||||
it.endToEnd = 0
|
||||
}
|
||||
fullscreenNotificationIconArea.layoutDirection = View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
|
||||
//增加一个左对齐布局
|
||||
mLeftLayout = LinearLayout(context)
|
||||
val leftLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f
|
||||
)
|
||||
mLeftLayout!!.layoutParams = leftLp
|
||||
mLeftLayout!!.gravity = Gravity.START or Gravity.CENTER_VERTICAL
|
||||
|
||||
//增加一个居中布局
|
||||
mCenterLayout = LinearLayout(context)
|
||||
val centerLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
mCenterLayout!!.layoutParams = centerLp
|
||||
mCenterLayout!!.gravity = Gravity.CENTER or Gravity.CENTER_VERTICAL
|
||||
|
||||
//增加一个右布局
|
||||
mRightLayout = LinearLayout(context)
|
||||
val rightLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
|
||||
0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f
|
||||
)
|
||||
mRightLayout!!.layoutParams = rightLp
|
||||
mRightLayout!!.gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
||||
|
||||
|
||||
mLeftLayout!!.addView(phoneStatusBarLeftContainer)
|
||||
mLeftLayout!!.addView(statusIcons)
|
||||
statusIcons.layoutDirection = View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
mCenterLayout!!.addView(clock)
|
||||
|
||||
mRightLayout!!.addView(mConstraintLayout)
|
||||
fullscreenNotificationIconArea.layoutDirection = View.LAYOUT_DIRECTION_RTL
|
||||
|
||||
|
||||
statusBarContents.addView(mLeftLayout, 0)
|
||||
statusBarContents.addView(mCenterLayout)
|
||||
statusBarContents.addView(mRightLayout)
|
||||
|
||||
|
||||
statusBarLeft = statusBar!!.paddingLeft
|
||||
statusBarTop = statusBar!!.paddingTop
|
||||
statusBarRight = statusBar!!.paddingRight
|
||||
statusBarBottom = statusBar!!.paddingBottom
|
||||
|
||||
|
||||
if (isCompatibilityMode) {
|
||||
val customLeftMargin = XSPUtils.getInt("status_bar_left_margin", 0)
|
||||
if (customLeftMargin != 0) {
|
||||
statusBarLeft = customLeftMargin
|
||||
}
|
||||
|
||||
val customRightMargin = XSPUtils.getInt("status_bar_right_margin", 0)
|
||||
if (customRightMargin != 0) {
|
||||
statusBarRight = customRightMargin
|
||||
}
|
||||
updateLayout(context, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//兼容模式
|
||||
"com.android.systemui.statusbar.phone.PhoneStatusBarView".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "updateLayoutForCutout"
|
||||
}
|
||||
afterHook {
|
||||
if (isCompatibilityMode) {
|
||||
val context = instance<ViewGroup>().context
|
||||
updateLayout(context, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//解决重叠
|
||||
"com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "showClock"
|
||||
param { it[0] == Boolean::class.java }
|
||||
}
|
||||
afterHook {
|
||||
val miuiPhoneStatusBarView = instance.current().field {
|
||||
name = "mStatusBar"
|
||||
superClass(true)
|
||||
}.cast<ViewGroup>()!!
|
||||
val res = miuiPhoneStatusBarView.resources
|
||||
val statusBarId = res.getIdentifier("status_bar", "id", "com.android.systemui")
|
||||
val statusBar1 = miuiPhoneStatusBarView.findViewById<ViewGroup>(statusBarId)
|
||||
//非锁屏下整个状态栏布局
|
||||
val keyguardMgr = statusBar1.context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
||||
if (keyguardMgr.isKeyguardLocked) {
|
||||
statusBar1!!.visibility = View.GONE
|
||||
} else {
|
||||
statusBar1!!.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.lt2333.simplicitytools.utils.hasEnable
|
||||
|
||||
object StatusBarNetworkSpeedRefreshSpeedForT : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
"com.android.systemui.statusbar.policy.NetworkSpeedController".hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "postUpdateNetworkSpeedDelay"
|
||||
param { it[0] == Long::class.java }
|
||||
}
|
||||
beforeHook {
|
||||
hasEnable("status_bar_network_speed_refresh_speed") {
|
||||
args[0] = 1000L
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
package com.lt2333.simplicitytools.hooks.rules.t.systemui
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.provider.Settings
|
||||
import android.util.TypedValue
|
||||
import android.view.Gravity
|
||||
import android.widget.TextView
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.lt2333.simplicitytools.utils.XSPUtils
|
||||
import java.lang.reflect.Method
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
|
||||
object StatusBarTimeCustomizationForT : YukiBaseHooker() {
|
||||
|
||||
private val getMode = XSPUtils.getInt("custom_clock_mode", 0)
|
||||
private val getClockSize = XSPUtils.getInt("status_bar_clock_size", 0)
|
||||
private val getClockDoubleSize = XSPUtils.getInt("status_bar_clock_double_line_size", 0)
|
||||
private val isYear = XSPUtils.getBoolean("status_bar_time_year", false)
|
||||
private val isMonth = XSPUtils.getBoolean("status_bar_time_month", false)
|
||||
private val isDay = XSPUtils.getBoolean("status_bar_time_day", false)
|
||||
private val isWeek = XSPUtils.getBoolean("status_bar_time_week", false)
|
||||
private val isHideSpace = XSPUtils.getBoolean("status_bar_time_hide_space", false)
|
||||
private val isDoubleLine = XSPUtils.getBoolean("status_bar_time_double_line", false)
|
||||
private val isSecond = XSPUtils.getBoolean("status_bar_time_seconds", false)
|
||||
private val isDoubleHour = XSPUtils.getBoolean("status_bar_time_double_hour", false)
|
||||
private val isPeriod = XSPUtils.getBoolean("status_bar_time_period", true)
|
||||
private val isCenterAlign = XSPUtils.getBoolean("status_bar_time_double_line_center_align", false)
|
||||
|
||||
//极客模式
|
||||
private val getGeekClockSize = XSPUtils.getInt("status_bar_clock_size_geek", 0)
|
||||
private val getGeekFormat = XSPUtils.getString("custom_clock_format_geek", "HH:mm:ss")
|
||||
private val isGeekCenterAlign = XSPUtils.getBoolean("status_bar_time_center_align_geek", false)
|
||||
|
||||
private lateinit var nowTime: Date
|
||||
private var str = ""
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onHook() {
|
||||
when (getMode) {
|
||||
//预设模式
|
||||
1 -> {
|
||||
var c: Context? = null
|
||||
|
||||
"com.android.systemui.statusbar.views.MiuiClock".hook {
|
||||
injectMember {
|
||||
constructor {
|
||||
paramCount = 3
|
||||
}
|
||||
afterHook {
|
||||
try {
|
||||
c = args[0] as Context
|
||||
val textV = instance<TextView>()
|
||||
if (textV.resources.getResourceEntryName(textV.id) != "clock") return@afterHook
|
||||
textV.isSingleLine = false
|
||||
if (isDoubleLine) {
|
||||
str = "\n"
|
||||
var clockDoubleLineSize = 7F
|
||||
if (getClockDoubleSize != 0) {
|
||||
clockDoubleLineSize = getClockDoubleSize.toFloat()
|
||||
}
|
||||
textV.setTextSize(
|
||||
TypedValue.COMPLEX_UNIT_DIP,
|
||||
clockDoubleLineSize
|
||||
)
|
||||
textV.setLineSpacing(0F, 0.8F)
|
||||
} else {
|
||||
if (getClockSize != 0) {
|
||||
val clockSize = getClockSize.toFloat()
|
||||
textV.setTextSize(TypedValue.COMPLEX_UNIT_DIP, clockSize)
|
||||
}
|
||||
}
|
||||
val d: Method = textV.javaClass.getDeclaredMethod("updateTime")
|
||||
val r = Runnable {
|
||||
d.isAccessible = true
|
||||
d.invoke(textV)
|
||||
}
|
||||
|
||||
class T : TimerTask() {
|
||||
override fun run() {
|
||||
Handler(textV.context.mainLooper).post(r)
|
||||
}
|
||||
}
|
||||
Timer().scheduleAtFixedRate(
|
||||
T(), 1000 - System.currentTimeMillis() % 1000, 1000
|
||||
)
|
||||
|
||||
if (isCenterAlign) {
|
||||
try {
|
||||
if (textV.resources.getResourceEntryName(textV.id) == "clock") {
|
||||
c = args[0] as Context
|
||||
textV.gravity = Gravity.CENTER
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method { name = "updateTime" }
|
||||
afterHook {
|
||||
try {
|
||||
val textV = instance<TextView>()
|
||||
if (textV.resources.getResourceEntryName(textV.id) == "clock") {
|
||||
val t = Settings.System.getString(
|
||||
c!!.contentResolver, Settings.System.TIME_12_24
|
||||
)
|
||||
val is24 = t == "24"
|
||||
nowTime = Calendar.getInstance().time
|
||||
textV.text = getDate(c!!) + str + getTime(c!!, is24)
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//极客模式
|
||||
2 -> {
|
||||
var c: Context? = null
|
||||
"com.android.systemui.statusbar.views.MiuiClock".hook {
|
||||
injectMember {
|
||||
constructor { paramCount = 3 }
|
||||
afterHook {
|
||||
try {
|
||||
c = args[0] as Context
|
||||
val textV = instance<TextView>()
|
||||
if (textV.resources.getResourceEntryName(textV.id) != "clock") return@afterHook
|
||||
textV.isSingleLine = false
|
||||
textV.setLineSpacing(0F, 0.8F)
|
||||
if (getGeekClockSize != 0) {
|
||||
val clockSize = getGeekClockSize.toFloat()
|
||||
textV.setTextSize(TypedValue.COMPLEX_UNIT_DIP, clockSize)
|
||||
}
|
||||
|
||||
val d: Method = textV.javaClass.getDeclaredMethod("updateTime")
|
||||
val r = Runnable {
|
||||
d.isAccessible = true
|
||||
d.invoke(textV)
|
||||
}
|
||||
|
||||
class T : TimerTask() {
|
||||
override fun run() {
|
||||
Handler(textV.context.mainLooper).post(r)
|
||||
}
|
||||
}
|
||||
Timer().scheduleAtFixedRate(
|
||||
T(), 1000 - System.currentTimeMillis() % 1000, 1000
|
||||
)
|
||||
|
||||
if (isGeekCenterAlign) {
|
||||
try {
|
||||
if (textV.resources.getResourceEntryName(textV.id) == "clock") {
|
||||
c = args[0] as Context
|
||||
textV.gravity = Gravity.CENTER
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method { name = "updateTime" }
|
||||
beforeHook {
|
||||
try {
|
||||
val textV = instance<TextView>()
|
||||
if (textV.resources.getResourceEntryName(textV.id) == "clock") {
|
||||
val resultSb = StringBuilder()
|
||||
val formatSb = StringBuilder(getGeekFormat.toString())
|
||||
|
||||
val mMiuiStatusBarClockController =
|
||||
textV.current()
|
||||
.field { name = "mMiuiStatusBarClockController" }
|
||||
val mCalendar =
|
||||
mMiuiStatusBarClockController.current()
|
||||
?.method { name = "getCalendar" }?.call()
|
||||
mCalendar?.current {
|
||||
method {
|
||||
name = "setTimeInMillis"
|
||||
paramCount = 1
|
||||
}.call(System.currentTimeMillis())
|
||||
method {
|
||||
name = "format"
|
||||
paramCount = 3
|
||||
returnType = StringBuilder::class.java
|
||||
}.call(c, resultSb, formatSb)
|
||||
}
|
||||
textV.text = resultSb.toString()
|
||||
resultNull()
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private fun getDate(context: Context): String {
|
||||
var datePattern = ""
|
||||
val isZh = isZh(context)
|
||||
|
||||
if (isYear) {
|
||||
if (isZh) {
|
||||
datePattern += "YY年"
|
||||
} else {
|
||||
datePattern += "YY"
|
||||
if (isMonth || isDay) datePattern += "/"
|
||||
}
|
||||
}
|
||||
if (isMonth) {
|
||||
if (isZh) {
|
||||
datePattern += "M月"
|
||||
} else {
|
||||
datePattern += "M"
|
||||
if (isDay) datePattern += "/"
|
||||
}
|
||||
}
|
||||
if (isDay) {
|
||||
datePattern += if (isZh) {
|
||||
"d日"
|
||||
} else {
|
||||
"d"
|
||||
}
|
||||
}
|
||||
if (isWeek) {
|
||||
if (!isHideSpace) datePattern = "$datePattern "
|
||||
datePattern += "E"
|
||||
if (!isDoubleLine) {
|
||||
if (!isHideSpace) datePattern = "$datePattern "
|
||||
}
|
||||
}
|
||||
datePattern = SimpleDateFormat(datePattern).format(nowTime)
|
||||
return datePattern
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private fun getTime(context: Context, t: Boolean): String {
|
||||
var timePattern = ""
|
||||
val isZh = isZh(context)
|
||||
timePattern += if (t) "HH:mm" else "h:mm"
|
||||
if (isSecond) timePattern += ":ss"
|
||||
timePattern = SimpleDateFormat(timePattern).format(nowTime)
|
||||
if (isZh) timePattern = getPeriod(isZh) + timePattern else timePattern += getPeriod(isZh)
|
||||
timePattern = getDoubleHour() + timePattern
|
||||
return timePattern
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private fun getPeriod(isZh: Boolean): String {
|
||||
var period = ""
|
||||
if (isPeriod) {
|
||||
if (isZh) {
|
||||
when (SimpleDateFormat("HH").format(nowTime)) {
|
||||
"00", "01", "02", "03", "04", "05" -> {
|
||||
period = "凌晨"
|
||||
}
|
||||
"06", "07", "08", "09", "10", "11" -> {
|
||||
period = "上午"
|
||||
}
|
||||
"12" -> {
|
||||
period = "中午"
|
||||
}
|
||||
"13", "14", "15", "16", "17" -> {
|
||||
period = "下午"
|
||||
}
|
||||
"18" -> {
|
||||
period = "傍晚"
|
||||
}
|
||||
"19", "20", "21", "22", "23" -> {
|
||||
period = "晚上"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
period = SimpleDateFormat("a").format(nowTime)
|
||||
if (!isHideSpace) {
|
||||
period = " $period"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return period
|
||||
}
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
private fun getDoubleHour(): String {
|
||||
var doubleHour = ""
|
||||
if (isDoubleHour) {
|
||||
when (SimpleDateFormat("HH").format(nowTime)) {
|
||||
"23", "00" -> {
|
||||
doubleHour = "子时"
|
||||
}
|
||||
"01", "02" -> {
|
||||
doubleHour = "丑时"
|
||||
}
|
||||
"03", "04" -> {
|
||||
doubleHour = "寅时"
|
||||
}
|
||||
"05", "06" -> {
|
||||
doubleHour = "卯时"
|
||||
}
|
||||
"07", "08" -> {
|
||||
doubleHour = "辰时"
|
||||
}
|
||||
"09", "10" -> {
|
||||
doubleHour = "巳时"
|
||||
}
|
||||
"11", "12" -> {
|
||||
doubleHour = "午时"
|
||||
}
|
||||
"13", "14" -> {
|
||||
doubleHour = "未时"
|
||||
}
|
||||
"15", "16" -> {
|
||||
doubleHour = "申时"
|
||||
}
|
||||
"17", "18" -> {
|
||||
doubleHour = "酉时"
|
||||
}
|
||||
"19", "20" -> {
|
||||
doubleHour = "戌时"
|
||||
}
|
||||
"21", "22" -> {
|
||||
doubleHour = "亥时"
|
||||
}
|
||||
}
|
||||
if (!isHideSpace) {
|
||||
doubleHour += " "
|
||||
}
|
||||
}
|
||||
return doubleHour
|
||||
}
|
||||
|
||||
private fun isZh(context: Context): Boolean {
|
||||
val locale = context.resources.configuration.locale
|
||||
val language = locale.language
|
||||
return language.endsWith("zh")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.lt2333.simplicitytools.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
|
||||
object SystemProperties {
|
||||
@SuppressLint("PrivateApi")
|
||||
operator fun get(context: Context, key: String?): String {
|
||||
var ret = ""
|
||||
try {
|
||||
val cl = context.classLoader
|
||||
val systemProperties = cl.loadClass("android.os.SystemProperties")
|
||||
//参数类型
|
||||
val paramTypes: Array<Class<*>?> = arrayOfNulls(1)
|
||||
paramTypes[0] = String::class.java
|
||||
val get = systemProperties.getMethod("get", *paramTypes)
|
||||
//参数
|
||||
val params = arrayOfNulls<Any>(1)
|
||||
params[0] = key
|
||||
ret = get.invoke(systemProperties, *params) as String
|
||||
} catch (iAE: IllegalArgumentException) {
|
||||
throw iAE
|
||||
} catch (e: Exception) {
|
||||
ret = ""
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.lt2333.simplicitytools.views
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.ContentObserver
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.text.TextUtils
|
||||
import android.widget.Toast
|
||||
|
||||
@SuppressLint("ViewConstructor", "SetTextI18n")
|
||||
class WeatherData(val context: Context?, private val showCity: Boolean) {
|
||||
|
||||
private val mContext: Context
|
||||
private val WEATHER_URI = Uri.parse("content://weather/weather")
|
||||
private val mHandler: Handler
|
||||
private val mWeatherObserver: ContentObserver?
|
||||
private val mWeatherRunnable: WeatherRunnable
|
||||
var weatherData: String = "\n"
|
||||
var callBacks: () -> Unit = {}
|
||||
|
||||
init {
|
||||
mHandler =
|
||||
object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(message: Message) {
|
||||
val str = message.obj as String
|
||||
weatherData = if (TextUtils.isEmpty(str)) "\n" else "$str\n"
|
||||
callBacks()
|
||||
}
|
||||
}
|
||||
mWeatherObserver = WeatherContentObserver(mHandler)
|
||||
mContext = context!!
|
||||
mWeatherRunnable = WeatherRunnable()
|
||||
context.contentResolver.registerContentObserver(WEATHER_URI, true, mWeatherObserver)
|
||||
updateWeatherInfo()
|
||||
}
|
||||
|
||||
private inner class WeatherContentObserver(handler: Handler?) : ContentObserver(handler) {
|
||||
override fun onChange(z: Boolean) {
|
||||
updateWeatherInfo()
|
||||
}
|
||||
}
|
||||
|
||||
inner class WeatherRunnable : Runnable {
|
||||
override fun run() {
|
||||
var str = ""
|
||||
try {
|
||||
val query = mContext.contentResolver.query(WEATHER_URI, null, null, null, null)
|
||||
if (query != null) {
|
||||
if (query.moveToFirst()) {
|
||||
str = if (showCity) {
|
||||
query.getString(query.getColumnIndexOrThrow("city_name")) + " " + query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString(query.getColumnIndexOrThrow("temperature"))
|
||||
} else {
|
||||
query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString(query.getColumnIndexOrThrow("temperature"))
|
||||
}
|
||||
}
|
||||
query.close()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
||||
}
|
||||
val obtainMessage2 = mHandler.obtainMessage()
|
||||
obtainMessage2.what = 100
|
||||
obtainMessage2.obj = str
|
||||
mHandler.sendMessage(obtainMessage2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWeatherInfo() {
|
||||
mHandler.removeCallbacks(mWeatherRunnable)
|
||||
mHandler.postDelayed(mWeatherRunnable, 200)
|
||||
}
|
||||
|
||||
fun onDetachedFromWindow() {
|
||||
if (mWeatherObserver != null) {
|
||||
mContext.contentResolver.unregisterContentObserver(mWeatherObserver)
|
||||
}
|
||||
}
|
||||
|
||||
fun startWeatherApp() {
|
||||
try {
|
||||
val intent = Intent().apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
component = ComponentName(
|
||||
"com.miui.weather2",
|
||||
"com.miui.weather2.ActivityWeatherMain"
|
||||
)
|
||||
}
|
||||
mContext.startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(context, "启动失败", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.lt2333.simplicitytools.views
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.database.ContentObserver
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.Message
|
||||
import android.text.TextUtils
|
||||
import android.widget.TextView
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class WeatherView(context: Context?, private val showCity: Boolean) : TextView(context) {
|
||||
|
||||
private val mContext: Context
|
||||
private val weatherUri = Uri.parse("content://weather/weather")
|
||||
private val mHandler: Handler
|
||||
private val mWeatherObserver: ContentObserver?
|
||||
private val mWeatherRunnable: WeatherRunnable
|
||||
|
||||
init {
|
||||
mHandler =
|
||||
object : Handler(Looper.getMainLooper()) {
|
||||
override fun handleMessage(message: Message) {
|
||||
val str = message.obj as String
|
||||
this@WeatherView.text = if (TextUtils.isEmpty(str)) " " else str
|
||||
}
|
||||
}
|
||||
mWeatherObserver = WeatherContentObserver(mHandler)
|
||||
mContext = context!!
|
||||
mWeatherRunnable = WeatherRunnable()
|
||||
context.contentResolver.registerContentObserver(weatherUri, true, mWeatherObserver)
|
||||
updateWeatherInfo()
|
||||
}
|
||||
|
||||
private inner class WeatherContentObserver(handler: Handler?) : ContentObserver(handler) {
|
||||
override fun onChange(z: Boolean) {
|
||||
updateWeatherInfo()
|
||||
}
|
||||
}
|
||||
|
||||
inner class WeatherRunnable : Runnable {
|
||||
override fun run() {
|
||||
var str = ""
|
||||
try {
|
||||
val query = mContext.contentResolver.query(weatherUri, null, null, null, null)
|
||||
if (query != null) {
|
||||
if (query.moveToFirst()) {
|
||||
str = if (showCity) {
|
||||
query.getString(query.getColumnIndexOrThrow("city_name")) + " " + query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString(query.getColumnIndexOrThrow("temperature"))
|
||||
} else {
|
||||
query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString(query.getColumnIndexOrThrow("temperature"))
|
||||
}
|
||||
}
|
||||
query.close()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
||||
}
|
||||
val obtainMessage2 = mHandler.obtainMessage()
|
||||
obtainMessage2.what = 100
|
||||
obtainMessage2.obj = str
|
||||
mHandler.sendMessage(obtainMessage2)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateWeatherInfo() {
|
||||
mHandler.removeCallbacks(mWeatherRunnable)
|
||||
mHandler.postDelayed(mWeatherRunnable, 200)
|
||||
}
|
||||
|
||||
public override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
if (mWeatherObserver != null) {
|
||||
mContext.contentResolver.unregisterContentObserver(mWeatherObserver)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.4.1' apply false
|
||||
id 'com.android.library' version '7.4.1' apply false
|
||||
id 'com.android.application' version '7.4.2' apply false
|
||||
id 'com.android.library' version '7.4.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user