23 Commits

Author SHA1 Message Date
LittleTurtle2333
1af8e0605b Update StatusBarLayoutForT.kt 2023-03-06 15:44:23 +08:00
LittleTurtle2333
29fa75cca0 优化写法 2023-03-06 15:44:02 +08:00
LittleTurtle2333
84f826fc31 Update SystemUIHooker.kt 2023-03-06 15:41:21 +08:00
LittleTurtle2333
719e7dfac1 Update AGP to 7.4.2 2023-03-06 15:41:06 +08:00
LittleTurtle2333
f77f9be2af Update OldNotificationWeatherForT.kt 2023-03-05 22:27:54 +08:00
LittleTurtle2333
c81951da2a Update AndroidHooker.kt 2023-03-05 22:07:28 +08:00
LittleTurtle2333
074a0fa160 Update HideBatteryIconForT.kt 2023-03-05 22:07:18 +08:00
LittleTurtle2333
ab5abc10c9 Update HideHDIconForT.kt 2023-03-05 22:07:08 +08:00
LittleTurtle2333
8117809073 Update NotificationWeatherForT.kt 2023-03-05 22:07:00 +08:00
LittleTurtle2333
ce5312494c Update SystemUIHooker.kt 2023-03-05 22:06:42 +08:00
LittleTurtle2333
3ce5d1b1f2 修复MIUI14上控制中心的天气显示 2023-03-05 22:06:05 +08:00
LittleTurtle2333
2737cd2492 修复一处MIUI14的问题 2023-03-05 20:26:13 +08:00
LittleTurtle2333
3d2e315113 Update SystemUIHooker.kt 2023-02-27 17:44:17 +08:00
LittleTurtle2333
3fbfaa218f Update WeatherData.kt && WeatherView.kt 2023-02-27 17:43:58 +08:00
LittleTurtle2333
51759aa199 Update SystemProperties.kt 2023-02-27 17:43:44 +08:00
LittleTurtle2333
7449d6e890 Update RemoveTheLeftSideOfTheLockScreenForT.kt 2023-02-27 17:43:37 +08:00
LittleTurtle2333
1b625d07eb Update RemoveLockScreenCameraForT.kt 2023-02-27 17:43:24 +08:00
LittleTurtle2333
d47aa371ab Update NotificationWeatherForT.kt 2023-02-27 17:43:16 +08:00
LittleTurtle2333
dae0b60c40 Update StatusBarTimeCustomizationForT.kt 2023-02-27 17:42:55 +08:00
LittleTurtle2333
74df408148 Update StatusBarTimeCustomizationForT.kt 2023-02-27 16:43:28 +08:00
LittleTurtle2333
62d2666c41 Update StatusBarTimeCustomizationForT.kt 2023-02-27 16:30:26 +08:00
LittleTurtle2333
4f20d364c6 修改生成的apk名字 2023-02-24 18:08:29 +08:00
LittleTurtle2333
62f08e5bcf 更新 .gitignore 2023-02-24 18:07:45 +08:00
23 changed files with 1430 additions and 33 deletions

3
.gitignore vendored
View File

@@ -15,5 +15,4 @@
.externalNativeBuild .externalNativeBuild
.cxx .cxx
local.properties local.properties
/app/release/app-release.apk /app/release/*
/app/release/output-metadata.json

View File

@@ -14,8 +14,6 @@ android {
versionCode 75 versionCode 75
versionName '1.7.5-Yuki' versionName '1.7.5-Yuki'
buildConfigField("String", "BUILD_TIME", "\"${System.currentTimeMillis()}\"") buildConfigField("String", "BUILD_TIME", "\"${System.currentTimeMillis()}\"")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
@@ -44,6 +42,25 @@ android {
lintOptions { lintOptions {
checkReleaseBuilds false 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 { dependencies {

View File

@@ -8,14 +8,15 @@ import com.lt2333.simplicitytools.hooks.rules.all.android.DisableFlagSecureForAl
object AndroidHooker: YukiBaseHooker() { object AndroidHooker: YukiBaseHooker() {
override fun onHook() { override fun onHook() {
//判断Android版本号加载不同的Hooker
when (Build.VERSION.SDK_INT) { when (Build.VERSION.SDK_INT) {
Build.VERSION_CODES.TIRAMISU -> { Build.VERSION_CODES.TIRAMISU -> { //Android13
loadHooker(DisableFlagSecureForAll) //允许截图 loadHooker(DisableFlagSecureForAll) //允许截图
loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸 loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸
loadHooker(DeleteOnPostNotificationForAll) //上层显示 loadHooker(DeleteOnPostNotificationForAll) //上层显示
} }
Build.VERSION_CODES.S -> { Build.VERSION_CODES.S -> { //Android12
loadHooker(DisableFlagSecureForAll) //允许截图 loadHooker(DisableFlagSecureForAll) //允许截图
loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸 loadHooker(AllowUntrustedTouchesForAll) //允许不受信任触摸
loadHooker(DeleteOnPostNotificationForAll) //上层显示 loadHooker(DeleteOnPostNotificationForAll) //上层显示

View File

@@ -2,7 +2,23 @@ package com.lt2333.simplicitytools.hooks.apps
import android.os.Build import android.os.Build
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.lt2333.simplicitytools.hooks.rules.t.systemui.* 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() { object SystemUIHooker : YukiBaseHooker() {
override fun onHook() { override fun onHook() {
@@ -19,6 +35,12 @@ object SystemUIHooker : YukiBaseHooker() {
loadHooker(MaximumNumberOfNotificationIconsForT) //通知图标上限 loadHooker(MaximumNumberOfNotificationIconsForT) //通知图标上限
loadHooker(StatusBarNetworkSpeedRefreshSpeedForT) //状态栏网速秒刷新 loadHooker(StatusBarNetworkSpeedRefreshSpeedForT) //状态栏网速秒刷新
loadHooker(StatusBarTimeCustomizationForT) //状态栏时钟自定义 loadHooker(StatusBarTimeCustomizationForT) //状态栏时钟自定义
loadHooker(RemoveTheLeftSideOfTheLockScreenForT) //移除锁屏负一屏功能
loadHooker(RemoveLockScreenCameraForT) //移除锁屏相机功能
loadHooker(NotificationWeatherForT) //通知面板天气
loadHooker(NewControlCenterWeatherForT) //新控制中心天气
loadHooker(OldNotificationWeatherForT) //经典通知天气
loadHooker(StatusBarLayoutForT) //状态栏布局
} }
Build.VERSION_CODES.S -> { Build.VERSION_CODES.S -> {

View File

@@ -24,7 +24,7 @@ object DisableFlagSecureForAll : YukiBaseHooker() {
method { name = "setSecure" } method { name = "setSecure" }
beforeHook { beforeHook {
hasEnable("disable_flag_secure") { hasEnable("disable_flag_secure") {
this.args[0] = false args[0] = false
} }
} }
} }
@@ -32,10 +32,10 @@ object DisableFlagSecureForAll : YukiBaseHooker() {
allMembers(MembersType.CONSTRUCTOR) allMembers(MembersType.CONSTRUCTOR)
beforeHook { beforeHook {
hasEnable("disable_flag_secure") { hasEnable("disable_flag_secure") {
var flags = this.args[2] as Int var flags = args[2] as Int
val secureFlag = 128 val secureFlag = 128
flags = flags and secureFlag.inv() flags = flags and secureFlag.inv()
this.args[2] = flags args[2] = flags
} }
} }
} }

View File

@@ -9,10 +9,8 @@ import android.view.View
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.field import com.highcapable.yukihookapi.hook.factory.field
import com.highcapable.yukihookapi.hook.factory.toClass
import com.lt2333.simplicitytools.R import com.lt2333.simplicitytools.R
import com.lt2333.simplicitytools.utils.hasEnable import com.lt2333.simplicitytools.utils.hasEnable
import de.robv.android.xposed.XposedHelpers
object ShortcutAddSmallWindowForAll : YukiBaseHooker() { object ShortcutAddSmallWindowForAll : YukiBaseHooker() {
override fun onHook() = hasEnable("miuihome_shortcut_add_small_window") { override fun onHook() = hasEnable("miuihome_shortcut_add_small_window") {
@@ -51,8 +49,8 @@ object ShortcutAddSmallWindowForAll : YukiBaseHooker() {
paramCount = 2 paramCount = 2
} }
beforeHook { beforeHook {
val obj = this.args[0] val obj = args[0]
val view: View = this.args[1] as View val view: View = args[1] as View
val mShortTitle = obj?.current { val mShortTitle = obj?.current {
method { name = "getShortTitle" }.invoke<CharSequence>() method { name = "getShortTitle" }.invoke<CharSequence>()
} }

View File

@@ -1,7 +1,6 @@
package com.lt2333.simplicitytools.hooks.rules.t.systemui package com.lt2333.simplicitytools.hooks.rules.t.systemui
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
@@ -18,6 +17,7 @@ object HideBatteryIconForT : YukiBaseHooker() {
afterHook { afterHook {
//隐藏电池图标 //隐藏电池图标
hasEnable("hide_battery_icon") { hasEnable("hide_battery_icon") {
//从当前实例中获取名为mBatteryStyle的Field并转换成ImageView类型操作可见度
instance.current().field { name = "mBatteryStyle" }.cast<ImageView>()?.visibility = View.GONE instance.current().field { name = "mBatteryStyle" }.cast<ImageView>()?.visibility = View.GONE
if (instance.current().field { name = "mBatteryStyle" }.int() == 1) { if (instance.current().field { name = "mBatteryStyle" }.int() == 1) {
instance.current().field { name = "mBatteryDigitalView" }.cast<FrameLayout>()?.visibility = View.GONE instance.current().field { name = "mBatteryDigitalView" }.cast<FrameLayout>()?.visibility = View.GONE

View File

@@ -42,6 +42,7 @@ object HideHDIconForT : YukiBaseHooker() {
} }
private fun hide(it: HookParam) { private fun hide(it: HookParam) {
hasEnable("hide_big_hd_icon") { hasEnable("hide_big_hd_icon") {
//从当前实例中获取名为mVolte的Field并转换成ImageView类型操作可见度
it.instance.current().field {name = "mVolte" }.cast<ImageView>()?.visibility = View.GONE it.instance.current().field {name = "mVolte" }.cast<ImageView>()?.visibility = View.GONE
} }
hasEnable("hide_small_hd_icon") { hasEnable("hide_small_hd_icon") {

View File

@@ -12,7 +12,7 @@ object HideSimIconForT:YukiBaseHooker() {
param(MutableList::class.java) param(MutableList::class.java)
} }
beforeHook { beforeHook {
val list = this.args[0] as MutableList<*> val list = args[0] as MutableList<*>
val size = list.size val size = list.size
hasEnable("hide_sim_two_icon", extraCondition = { size == 2 }) { hasEnable("hide_sim_two_icon", extraCondition = { size == 2 }) {
list.removeAt(1) list.removeAt(1)

View File

@@ -13,13 +13,13 @@ object HideStatusBarNetworkSpeedSecondForT : YukiBaseHooker() {
} }
beforeHook { beforeHook {
hasEnable("hide_status_bar_network_speed_second") { hasEnable("hide_status_bar_network_speed_second") {
if (this.args[0] != null) { if (args[0] != null) {
val mText = (this.args[0] as String) val mText = (args[0] as String)
.replace("/", "") .replace("/", "")
.replace("s", "") .replace("s", "")
.replace("\'", "") .replace("\'", "")
.replace("วิ", "") .replace("วิ", "")
this.args[0] = mText args[0] = mText
} }
} }
} }

View File

@@ -3,7 +3,6 @@ package com.lt2333.simplicitytools.hooks.rules.t.systemui
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
import com.lt2333.simplicitytools.utils.XSPUtils import com.lt2333.simplicitytools.utils.XSPUtils
import java.lang.reflect.Method
object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() { object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() {
override fun onHook() { override fun onHook() {
@@ -16,14 +15,14 @@ object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() {
paramCount = 1 paramCount = 1
} }
replaceUnit { replaceUnit {
if (this.args[0] as Boolean) { if (args[0] as Boolean) {
instance.current().field { name = "MAX_DOTS" }.set(dots) instance.current().field { name = "MAX_DOTS" }.set(dots)
instance.current().field { name = "MAX_STATIC_ICONS" }.set(icons) instance.current().field { name = "MAX_STATIC_ICONS" }.set(icons)
instance.current().field { name = "MAX_VISIBLE_ICONS_ON_LOCK" }.set(icons) instance.current().field { name = "MAX_ICONS_ON_LOCKSCREEN" }.set(icons)
} else { } else {
instance.current().field { name = "MAX_DOTS" }.set(0) instance.current().field { name = "MAX_DOTS" }.set(0)
instance.current().field { name = "MAX_STATIC_ICONS" }.set(0) instance.current().field { name = "MAX_STATIC_ICONS" }.set(0)
instance.current().field { name = "MAX_VISIBLE_ICONS_ON_LOCK" }.set(0) instance.current().field { name = "MAX_ICONS_ON_LOCKSCREEN" }.set(0)
} }
instance.current().method { name = "updateState" }.call() instance.current().method { name = "updateState" }.call()
} }

View File

@@ -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 { }
}
}
}
}
}
}

View File

@@ -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
}
}
}
}
}
}
}

View File

@@ -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
}
}
}
}
}
}

View File

@@ -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
}
}
}
}
}
}

View File

@@ -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()
}
}
}
}
}
}

View File

@@ -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
}
}
}
}
}
}
}
}

View File

@@ -13,7 +13,7 @@ object StatusBarNetworkSpeedRefreshSpeedForT : YukiBaseHooker() {
} }
beforeHook { beforeHook {
hasEnable("status_bar_network_speed_refresh_speed") { hasEnable("status_bar_network_speed_refresh_speed") {
this.args[0] = 1000L args[0] = 1000L
} }
} }
} }

View File

@@ -3,12 +3,15 @@ package com.lt2333.simplicitytools.hooks.rules.t.systemui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.os.Handler import android.os.Handler
import android.provider.Settings
import android.util.TypedValue import android.util.TypedValue
import android.view.Gravity
import android.widget.TextView import android.widget.TextView
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.current
import com.lt2333.simplicitytools.utils.XSPUtils import com.lt2333.simplicitytools.utils.XSPUtils
import java.lang.reflect.Method import java.lang.reflect.Method
import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Timer import java.util.Timer
@@ -42,7 +45,84 @@ object StatusBarTimeCustomizationForT : YukiBaseHooker() {
override fun onHook() { override fun onHook() {
when (getMode) { when (getMode) {
//预设模式 //预设模式
1 -> {} 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 -> { 2 -> {
var c: Context? = null var c: Context? = null
@@ -51,7 +131,7 @@ object StatusBarTimeCustomizationForT : YukiBaseHooker() {
constructor { paramCount = 3 } constructor { paramCount = 3 }
afterHook { afterHook {
try { try {
c = this.args[0] as Context c = args[0] as Context
val textV = instance<TextView>() val textV = instance<TextView>()
if (textV.resources.getResourceEntryName(textV.id) != "clock") return@afterHook if (textV.resources.getResourceEntryName(textV.id) != "clock") return@afterHook
textV.isSingleLine = false textV.isSingleLine = false
@@ -75,13 +155,20 @@ object StatusBarTimeCustomizationForT : YukiBaseHooker() {
Timer().scheduleAtFixedRate( Timer().scheduleAtFixedRate(
T(), 1000 - System.currentTimeMillis() % 1000, 1000 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) { } catch (_: Exception) {
} }
} }
} }
}
"com.android.systemui.statusbar.views.MiuiClock".hook {
injectMember { injectMember {
method { name = "updateTime" } method { name = "updateTime" }
beforeHook { beforeHook {
@@ -92,9 +179,11 @@ object StatusBarTimeCustomizationForT : YukiBaseHooker() {
val formatSb = StringBuilder(getGeekFormat.toString()) val formatSb = StringBuilder(getGeekFormat.toString())
val mMiuiStatusBarClockController = val mMiuiStatusBarClockController =
textV.current().field { name = "mMiuiStatusBarClockController" } textV.current()
.field { name = "mMiuiStatusBarClockController" }
val mCalendar = val mCalendar =
mMiuiStatusBarClockController.current()?.method { name = "getCalendar" }?.call() mMiuiStatusBarClockController.current()
?.method { name = "getCalendar" }?.call()
mCalendar?.current { mCalendar?.current {
method { method {
name = "setTimeInMillis" name = "setTimeInMillis"
@@ -117,4 +206,145 @@ object StatusBarTimeCustomizationForT : YukiBaseHooker() {
} }
} }
} }
@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")
}
} }

View File

@@ -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
}
}

View File

@@ -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()
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -1,6 +1,6 @@
plugins { plugins {
id 'com.android.application' version '7.4.1' apply false id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.1' apply false id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.10' apply false id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
} }