24 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
LittleTurtle2333
98876ddbd2 更新1个系统界面Hooker 2023-02-24 16:49:22 +08:00
23 changed files with 1554 additions and 26 deletions

3
.gitignore vendored
View File

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

View File

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

View File

@@ -8,14 +8,15 @@ import com.lt2333.simplicitytools.hooks.rules.all.android.DisableFlagSecureForAl
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) //上层显示

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,6 @@
package com.lt2333.simplicitytools.hooks.rules.t.systemui
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
@@ -18,6 +17,7 @@ object HideBatteryIconForT : YukiBaseHooker() {
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

View File

@@ -42,6 +42,7 @@ object HideHDIconForT : YukiBaseHooker() {
}
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") {

View File

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

View File

@@ -13,13 +13,13 @@ object HideStatusBarNetworkSpeedSecondForT : YukiBaseHooker() {
}
beforeHook {
hasEnable("hide_status_bar_network_speed_second") {
if (this.args[0] != null) {
val mText = (this.args[0] as String)
if (args[0] != null) {
val mText = (args[0] as String)
.replace("/", "")
.replace("s", "")
.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.factory.current
import com.lt2333.simplicitytools.utils.XSPUtils
import java.lang.reflect.Method
object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() {
override fun onHook() {
@@ -16,14 +15,14 @@ object MaximumNumberOfNotificationIconsForT: YukiBaseHooker() {
paramCount = 1
}
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_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 {
instance.current().field { name = "MAX_DOTS" }.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()
}

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 {
hasEnable("status_bar_network_speed_refresh_speed") {
this.args[0] = 1000L
args[0] = 1000L
}
}
}

View File

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

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