diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 8541829389..0000000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123c2b..0000000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 96f74dd8b2..8e916f8dd5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -232,7 +232,7 @@ dependencies { implementation(libs.lyric.getter.api) implementation(libs.lunarcalendar) - implementation(project(":app:provision")) - implementation(project(":app:processor")) - annotationProcessor(project(":app:processor")) + implementation(project(":provision")) + implementation(project(":processor")) + annotationProcessor(project(":processor")) } diff --git a/app/proguard-log.pro b/app/proguard-log.pro deleted file mode 100644 index 151518a3d5..0000000000 --- a/app/proguard-log.pro +++ /dev/null @@ -1,54 +0,0 @@ -########################################################################################################## -# 作者:Sollyu -# 日期:2020-11-02 -# 内容:发布版本移除日志,kotlin编译时带的而外信息,增强反调试难度 -# 使用:proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro' -########################################################################################################## - -########################################################################################################## -# 删除安卓日志 --assumenosideeffects class android.util.Log { - public static *** d(...); - public static *** v(...); - public static *** w(...); - public static *** e(...); -} - -########################################################################################################## -# 删除Kotlin编译时可能生成显示变量的方法 --assumenosideeffects class kotlin.jvm.internal.Intrinsics { - public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String); - public static void checkFieldIsNotNull(java.lang.Object, java.lang.String); - public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String); - public static void checkNotNull(java.lang.Object); - public static void checkNotNull(java.lang.Object, java.lang.String); - public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String); - public static void checkNotNullParameter(java.lang.Object, java.lang.String); - public static void checkParameterIsNotNull(java.lang.Object, java.lang.String); - public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String); - public static void throwUninitializedPropertyAccessException(java.lang.String); -} - -########################################################################################################## -# 会暴露变量名称 --assumenosideeffects class java.util.Objects { - public static java.lang.Object requireNonNull(java.lang.Object, java.lang.String); -} - -########################################################################################################## -# 删除slf4j的日志输出 --assumenosideeffects interface org.slf4j.Logger { - public void trace(...); - public void debug(...); - public void info(...); - public void warn(...); - public void error(...); - - public boolean isTraceEnabled(...); - public boolean isDebugEnabled(...); - public boolean isWarnEnabled(...); -} - --assumenosideeffects class org.slf4j.LoggerFactory { - public static ** getLogger(...); -} diff --git a/app/provision/build.gradle.kts b/app/provision/build.gradle.kts deleted file mode 100644 index 499983d09b..0000000000 --- a/app/provision/build.gradle.kts +++ /dev/null @@ -1,45 +0,0 @@ -plugins { - alias(libs.plugins.android.library) -} - -android { - namespace = "com.sevtinge.provision" - compileSdk = 35 - - defaultConfig { - minSdk = 33 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_22 - targetCompatibility = JavaVersion.VERSION_22 - } -} - -val buildTypes = "debug" - -dependencies { - api(libs.core) - api(libs.collection) - api(libs.recyclerview) - api(libs.fragment) - api(libs.lifecycle.common) - api(libs.coordinatorlayout) - api(libs.constraintlayout) { - exclude("androidx.appcompat", "appcompat") - } - - api(fileTree(mapOf("dir" to "../libs", "include" to listOf("*-${buildTypes}.aar")))) -} \ No newline at end of file diff --git a/app/provision/src/main/AndroidManifest.xml b/app/provision/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e68ab..0000000000 --- a/app/provision/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiU.java b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiU.java index 5ed8c08b2b..aa33f50a2f 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiU.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiU.java @@ -32,6 +32,7 @@ import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFix; import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFreeform; import com.sevtinge.hyperceiler.module.hook.systemui.RemoveMiuiMultiWinSwitch; +import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.OldWeather; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.MediaPicture; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.SquigglyProgress; import com.sevtinge.hyperceiler.module.hook.systemui.StatusBarActions; @@ -251,6 +252,7 @@ public void handleLoadPackage() { mPrefsMap.getBoolean("system_control_center_qs_tile_label")); initHook(new MuteVisibleNotifications(), mPrefsMap.getBoolean("system_ui_control_center_mute_visible_notice")); initHook(new SwitchCCAndNotification(), mPrefsMap.getBoolean("system_ui_control_center_switch_cc_and_notification")); + initHook(OldWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(CompactNotificationsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_compact_notice")); /*initHook(CCGridOld.INSTANCE, mPrefsMap.getInt("system_control_center_cc_rows", 4) > 4 || diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiV.java b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiV.java index f40fe07385..2585be2d1b 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiV.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Pad/SystemUiV.java @@ -32,6 +32,7 @@ import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFix; import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFreeform; import com.sevtinge.hyperceiler.module.hook.systemui.RemoveMiuiMultiWinSwitch; +import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.OldWeather; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.MediaPicture; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.SquigglyProgress; import com.sevtinge.hyperceiler.module.hook.systemui.StatusBarActions; @@ -205,6 +206,7 @@ public void handleLoadPackage() { mPrefsMap.getBoolean("system_control_center_qs_tile_label")); initHook(new MuteVisibleNotifications(), mPrefsMap.getBoolean("system_ui_control_center_mute_visible_notice")); initHook(new SwitchCCAndNotification(), mPrefsMap.getBoolean("system_ui_control_center_switch_cc_and_notification")); + initHook(OldWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(CompactNotificationsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_compact_notice")); /*initHook(CCGridOld.INSTANCE, mPrefsMap.getInt("system_control_center_cc_rows", 4) > 4 || diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiU.java b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiU.java index 81b7df51b2..e0c03ba633 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiU.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiU.java @@ -32,6 +32,7 @@ import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFix; import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFreeform; import com.sevtinge.hyperceiler.module.hook.systemui.RemoveMiuiMultiWinSwitch; +import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.OldWeather; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.MediaPicture; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.SquigglyProgress; import com.sevtinge.hyperceiler.module.hook.systemui.StatusBarActions; @@ -242,6 +243,7 @@ public void handleLoadPackage() { mPrefsMap.getBoolean("system_control_center_qs_tile_label")); initHook(new MuteVisibleNotifications(), mPrefsMap.getBoolean("system_ui_control_center_mute_visible_notice")); initHook(new SwitchCCAndNotification(), mPrefsMap.getBoolean("system_ui_control_center_switch_cc_and_notification")); + initHook(OldWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(CompactNotificationsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_compact_notice")); /*initHook(CCGridOld.INSTANCE, mPrefsMap.getInt("system_control_center_cc_rows", 4) > 4 || diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiV.java b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiV.java index 762da24669..73cf4fc143 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiV.java +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/app/SystemUI/Phone/SystemUiV.java @@ -33,6 +33,7 @@ import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFix; import com.sevtinge.hyperceiler.module.hook.systemui.NotificationFreeform; import com.sevtinge.hyperceiler.module.hook.systemui.RemoveMiuiMultiWinSwitch; +import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.OldWeather; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.MediaPicture; import com.sevtinge.hyperceiler.module.hook.systemui.controlcenter.media.SquigglyProgress; import com.sevtinge.hyperceiler.module.hook.systemui.StatusBarActions; @@ -232,6 +233,7 @@ public void handleLoadPackage() { // mPrefsMap.getBoolean("system_control_center_qs_tile_label")); initHook(new MuteVisibleNotifications(), mPrefsMap.getBoolean("system_ui_control_center_mute_visible_notice")); initHook(new SwitchCCAndNotification(), mPrefsMap.getBoolean("system_ui_control_center_switch_cc_and_notification")); + initHook(OldWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(CompactNotificationsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_compact_notice")); initHook(new QSGrid(), mPrefsMap.getBoolean("system_control_center_old_enable")); diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/NotificationWeather.kt b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/NotificationWeather.kt index fb6d4d7e94..3f4751831f 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/NotificationWeather.kt +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/NotificationWeather.kt @@ -19,7 +19,6 @@ package com.sevtinge.hyperceiler.module.hook.systemui.controlcenter import android.annotation.* -import android.content.* import android.content.res.Configuration.ORIENTATION_LANDSCAPE import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.view.* @@ -30,7 +29,6 @@ import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createAfterHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createBeforeHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.hyperceiler.module.base.* -import com.sevtinge.hyperceiler.module.hook.systemui.* import com.sevtinge.hyperceiler.utils.* import com.sevtinge.hyperceiler.utils.api.LazyClass.miuiConfigs import com.sevtinge.hyperceiler.utils.devicesdk.* @@ -50,24 +48,6 @@ object NotificationWeather : BaseHook() { // 及动画 private var vWeatherViewFolme: Any? = null - // 天气组件点击事件 - private val weatherViewClickListener = View.OnClickListener { - val intent = Intent().apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK - component = ComponentName( - "com.miui.weather2", - "com.miui.weather2.ActivityWeatherMain" - ) - } - - val clz = findClass(InterfacesImplManager.I_ACTIVITY_STARTER) - if (isMoreHyperOSVersion(2f)) { - InterfacesImplManager.sClassContainer[clz] - } else { - Dependency.get(clz) - }?.callMethod("startActivity", intent, true) - } - // 是否显示城市 private val isDisplayCity by lazy { mPrefsMap.getBoolean("system_ui_control_center_show_weather_city") @@ -292,7 +272,9 @@ object NotificationWeather : BaseHook() { ) + dp2px(5f) } - setOnClickListener(weatherViewClickListener) + setOnClickListener { + startWeatherApp() + } } val viewParent = view.parent as ViewGroup diff --git a/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/OldWeather.kt b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/OldWeather.kt new file mode 100644 index 0000000000..1775b4c687 --- /dev/null +++ b/app/src/main/java/com/sevtinge/hyperceiler/module/hook/systemui/controlcenter/OldWeather.kt @@ -0,0 +1,99 @@ +/* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2024 HyperCeiler Contributions +*/ +package com.sevtinge.hyperceiler.module.hook.systemui.controlcenter + +import android.annotation.SuppressLint +import android.view.ViewGroup +import android.widget.TextView +import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass +import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook +import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder +import com.sevtinge.hyperceiler.module.base.BaseHook + +import com.sevtinge.hyperceiler.utils.setObjectField +import com.sevtinge.hyperceiler.view.WeatherView + +// 经典控制中心添加天气信息 +object OldWeather : BaseHook() { + private val isDisplayCity by lazy { + mPrefsMap.getBoolean("system_ui_control_center_show_weather_city") + } + + @SuppressLint("DiscouragedApi") + override fun init() { + var mWeatherView: TextView? + loadClass("com.android.systemui.qs.MiuiQSHeaderView").methodFinder() + .filterByName("onFinishInflate") + .first().createHook { + after { + val viewGroup = it.thisObject as ViewGroup + val context = viewGroup.context + val layoutParam = + loadClass("androidx.constraintlayout.widget.ConstraintLayout\$LayoutParams") + .getConstructor(Int::class.java, Int::class.java) + .newInstance( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) as ViewGroup.MarginLayoutParams + + layoutParam.setObjectField( + "endToStart", + context.resources.getIdentifier( + "notification_shade_shortcut", + "id", + context.packageName + ) + ) + layoutParam.setObjectField( + "topToTop", + context.resources.getIdentifier( + "notification_shade_shortcut", + "id", + context.packageName + ) + ) + layoutParam.setObjectField( + "bottomToBottom", + context.resources.getIdentifier( + "notification_shade_shortcut", + "id", + context.packageName + ) + ) + + mWeatherView = WeatherView(context, isDisplayCity).apply { + setTextAppearance( + context.resources.getIdentifier( + "TextAppearance.StatusBar.Expanded.Clock.QuickSettingDate", + "style", + context.packageName + ) + ) + layoutParams = layoutParam + + setOnClickListener { + startWeatherApp() + } + } + viewGroup.addView(mWeatherView) + } + } + } + +} diff --git a/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherData.kt b/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherData.kt deleted file mode 100644 index 15d60fc0a0..0000000000 --- a/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherData.kt +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of HyperCeiler. - - * HyperCeiler is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - - * Copyright (C) 2023-2025 HyperCeiler Contributions -*/ -package com.sevtinge.hyperceiler.view - -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 -import com.sevtinge.hyperceiler.utils.api.argTypes -import com.sevtinge.hyperceiler.utils.api.args -import com.sevtinge.hyperceiler.utils.callStaticMethod - -@SuppressLint("ViewConstructor", "SetTextI18n") -class WeatherData(val context: Context?, private val showCity: Boolean) { - - private val mContext: Context - private val mWeatherUri = 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(mWeatherUri, 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(mWeatherUri, 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 (_: 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 startCalendarApp() { - mContext.classLoader.loadClass("com.miui.systemui.util.CommonUtil") - .callStaticMethod("startCalendarApp", args(context), argTypes(Context::class.java)) - } - - 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() - } - } -} diff --git a/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherView.kt b/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherView.kt index 229f6e69fd..b59456855e 100644 --- a/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherView.kt +++ b/app/src/main/java/com/sevtinge/hyperceiler/view/WeatherView.kt @@ -19,34 +19,38 @@ package com.sevtinge.hyperceiler.view 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.TextView +import androidx.core.net.toUri +import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass +import com.sevtinge.hyperceiler.module.hook.systemui.Dependency +import com.sevtinge.hyperceiler.module.hook.systemui.InterfacesImplManager +import com.sevtinge.hyperceiler.utils.callMethod +import com.sevtinge.hyperceiler.utils.devicesdk.isMoreHyperOSVersion @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 = object : Handler(Looper.getMainLooper()) { + private val mContext: Context = context!! + private val weatherUri = "content://weather/weather".toUri() + private val mHandler: Handler = object : Handler(mContext.mainLooper) { override fun handleMessage(message: Message) { val str = message.obj as String this@WeatherView.text = if (TextUtils.isEmpty(str)) " " else str } } - private val mWeatherObserver: ContentObserver? + private val mWeatherObserver = WeatherContentObserver(mHandler) private val mWeatherRunnable: WeatherRunnable init { - mWeatherObserver = WeatherContentObserver(mHandler) - mContext = context!! mWeatherRunnable = WeatherRunnable() - context.contentResolver.registerContentObserver(weatherUri, true, mWeatherObserver) + context?.contentResolver?.registerContentObserver(weatherUri, true, mWeatherObserver) updateWeatherInfo() } @@ -59,33 +63,29 @@ class WeatherView(context: Context?, private val showCity: Boolean) : TextView(c 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" - ) + mContext.contentResolver.query(weatherUri, null, null, null, null)?.use { query -> + 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 (_: Exception) { + } + mHandler.obtainMessage().apply { + what = 100 + obj = str + mHandler.sendMessage(this) } - val obtainMessage2 = mHandler.obtainMessage() - obtainMessage2.what = 100 - obtainMessage2.obj = str - mHandler.sendMessage(obtainMessage2) } } @@ -101,4 +101,23 @@ class WeatherView(context: Context?, private val showCity: Boolean) : TextView(c } } + fun startWeatherApp() { + runCatching { + val intent = Intent().apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + component = ComponentName( + "com.miui.weather2", + "com.miui.weather2.ActivityWeatherMain" + ) + } + + val clz = loadClass(InterfacesImplManager.I_ACTIVITY_STARTER) + if (isMoreHyperOSVersion(2f)) { + InterfacesImplManager.sClassContainer[clz] + } else { + Dependency.get(clz) + }?.callMethod("startActivity", intent, true) + } + } + } diff --git a/app/processor/build.gradle b/build.gradle similarity index 100% rename from app/processor/build.gradle rename to build.gradle diff --git a/local.properties b/local.properties new file mode 100644 index 0000000000..52e989ecc8 --- /dev/null +++ b/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Sat Aug 05 22:58:23 CST 2023 +sdk.dir=D\:\\Android\\SDK diff --git a/app/processor/.gitignore b/processor/.gitignore similarity index 100% rename from app/processor/.gitignore rename to processor/.gitignore diff --git a/processor/build.gradle.kts b/processor/build.gradle.kts new file mode 100644 index 0000000000..c8c483dc16 --- /dev/null +++ b/processor/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("java-library") +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +dependencies { + implementation(libs.auto.service) + annotationProcessor(libs.auto.service) +} \ No newline at end of file diff --git a/app/processor/src/main/java/com/hchen/database/HookBase.java b/processor/src/main/java/com/hchen/database/HookBase.java similarity index 100% rename from app/processor/src/main/java/com/hchen/database/HookBase.java rename to processor/src/main/java/com/hchen/database/HookBase.java diff --git a/app/processor/src/main/java/com/hchen/database/HookBaseProcessor.java b/processor/src/main/java/com/hchen/database/HookBaseProcessor.java similarity index 100% rename from app/processor/src/main/java/com/hchen/database/HookBaseProcessor.java rename to processor/src/main/java/com/hchen/database/HookBaseProcessor.java diff --git a/app/provision/.gitignore b/provision/.gitignore similarity index 100% rename from app/provision/.gitignore rename to provision/.gitignore diff --git a/provision/build.gradle.kts b/provision/build.gradle.kts new file mode 100644 index 0000000000..dc640963b6 --- /dev/null +++ b/provision/build.gradle.kts @@ -0,0 +1,73 @@ +plugins { + alias(libs.plugins.android.library) +} + +android { + namespace = "com.sevtinge.provision" + compileSdk = 35 + + defaultConfig { + minSdk = 33 + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + create("beta") { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + create("canary") { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + debug { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } + } +} + +val buildTypes = "debug" + +dependencies { + api(libs.core) + api(libs.collection) + api(libs.recyclerview) + api(libs.fragment) + api(libs.lifecycle.common) + api(libs.coordinatorlayout) + api(libs.constraintlayout) { + exclude("androidx.appcompat", "appcompat") + } + + api(fileTree(mapOf("dir" to "libs", "include" to listOf("*-${buildTypes}.aar")))) +} \ No newline at end of file diff --git a/app/provision/consumer-rules.pro b/provision/consumer-rules.pro similarity index 100% rename from app/provision/consumer-rules.pro rename to provision/consumer-rules.pro diff --git a/app/libs/animation-debug.aar b/provision/libs/animation-debug.aar similarity index 100% rename from app/libs/animation-debug.aar rename to provision/libs/animation-debug.aar diff --git a/app/libs/appcompat-debug.aar b/provision/libs/appcompat-debug.aar similarity index 100% rename from app/libs/appcompat-debug.aar rename to provision/libs/appcompat-debug.aar diff --git a/app/libs/basewidget-debug.aar b/provision/libs/basewidget-debug.aar similarity index 100% rename from app/libs/basewidget-debug.aar rename to provision/libs/basewidget-debug.aar diff --git a/app/libs/bottomsheet-debug.aar b/provision/libs/bottomsheet-debug.aar similarity index 100% rename from app/libs/bottomsheet-debug.aar rename to provision/libs/bottomsheet-debug.aar diff --git a/app/libs/cardview-debug.aar b/provision/libs/cardview-debug.aar similarity index 100% rename from app/libs/cardview-debug.aar rename to provision/libs/cardview-debug.aar diff --git a/app/libs/core-debug.aar b/provision/libs/core-debug.aar similarity index 100% rename from app/libs/core-debug.aar rename to provision/libs/core-debug.aar diff --git a/app/libs/external-debug.aar b/provision/libs/external-debug.aar similarity index 100% rename from app/libs/external-debug.aar rename to provision/libs/external-debug.aar diff --git a/app/libs/flexible-debug.aar b/provision/libs/flexible-debug.aar similarity index 100% rename from app/libs/flexible-debug.aar rename to provision/libs/flexible-debug.aar diff --git a/app/libs/folme-debug.aar b/provision/libs/folme-debug.aar similarity index 100% rename from app/libs/folme-debug.aar rename to provision/libs/folme-debug.aar diff --git a/app/libs/graphics-debug.aar b/provision/libs/graphics-debug.aar similarity index 100% rename from app/libs/graphics-debug.aar rename to provision/libs/graphics-debug.aar diff --git a/app/libs/haptic-debug.aar b/provision/libs/haptic-debug.aar similarity index 100% rename from app/libs/haptic-debug.aar rename to provision/libs/haptic-debug.aar diff --git a/app/libs/hyperceiler_expansion_packs-debug.aar b/provision/libs/hyperceiler_expansion_packs-debug.aar similarity index 100% rename from app/libs/hyperceiler_expansion_packs-debug.aar rename to provision/libs/hyperceiler_expansion_packs-debug.aar diff --git a/app/libs/navigator-debug.aar b/provision/libs/navigator-debug.aar similarity index 100% rename from app/libs/navigator-debug.aar rename to provision/libs/navigator-debug.aar diff --git a/app/libs/nestedheader-debug.aar b/provision/libs/nestedheader-debug.aar similarity index 100% rename from app/libs/nestedheader-debug.aar rename to provision/libs/nestedheader-debug.aar diff --git a/app/libs/pickerwidget-debug.aar b/provision/libs/pickerwidget-debug.aar similarity index 100% rename from app/libs/pickerwidget-debug.aar rename to provision/libs/pickerwidget-debug.aar diff --git a/app/libs/popupwidget-debug.aar b/provision/libs/popupwidget-debug.aar similarity index 100% rename from app/libs/popupwidget-debug.aar rename to provision/libs/popupwidget-debug.aar diff --git a/app/libs/preference-debug.aar b/provision/libs/preference-debug.aar similarity index 100% rename from app/libs/preference-debug.aar rename to provision/libs/preference-debug.aar diff --git a/app/libs/recyclerview-debug.aar b/provision/libs/recyclerview-debug.aar similarity index 100% rename from app/libs/recyclerview-debug.aar rename to provision/libs/recyclerview-debug.aar diff --git a/app/libs/slidingwidget-debug.aar b/provision/libs/slidingwidget-debug.aar similarity index 100% rename from app/libs/slidingwidget-debug.aar rename to provision/libs/slidingwidget-debug.aar diff --git a/app/libs/smooth-debug.aar b/provision/libs/smooth-debug.aar similarity index 100% rename from app/libs/smooth-debug.aar rename to provision/libs/smooth-debug.aar diff --git a/app/libs/springback-debug.aar b/provision/libs/springback-debug.aar similarity index 100% rename from app/libs/springback-debug.aar rename to provision/libs/springback-debug.aar diff --git a/app/libs/stretchablewidget-debug.aar b/provision/libs/stretchablewidget-debug.aar similarity index 100% rename from app/libs/stretchablewidget-debug.aar rename to provision/libs/stretchablewidget-debug.aar diff --git a/app/libs/stub-debug.aar b/provision/libs/stub-debug.aar similarity index 100% rename from app/libs/stub-debug.aar rename to provision/libs/stub-debug.aar diff --git a/app/libs/theme-debug.aar b/provision/libs/theme-debug.aar similarity index 100% rename from app/libs/theme-debug.aar rename to provision/libs/theme-debug.aar diff --git a/app/libs/viewpager-debug.aar b/provision/libs/viewpager-debug.aar similarity index 100% rename from app/libs/viewpager-debug.aar rename to provision/libs/viewpager-debug.aar diff --git a/app/libs/visualcheck-debug.aar b/provision/libs/visualcheck-debug.aar similarity index 100% rename from app/libs/visualcheck-debug.aar rename to provision/libs/visualcheck-debug.aar diff --git a/app/provision/proguard-rules.pro b/provision/proguard-rules.pro similarity index 100% rename from app/provision/proguard-rules.pro rename to provision/proguard-rules.pro diff --git a/app/provision/src/main/java/com/sevtinge/provision/utils/IAnimCallback.java b/provision/src/main/java/com/sevtinge/provision/utils/IAnimCallback.java similarity index 100% rename from app/provision/src/main/java/com/sevtinge/provision/utils/IAnimCallback.java rename to provision/src/main/java/com/sevtinge/provision/utils/IAnimCallback.java diff --git a/app/provision/src/main/java/com/sevtinge/provision/utils/IKeyEvent.java b/provision/src/main/java/com/sevtinge/provision/utils/IKeyEvent.java similarity index 100% rename from app/provision/src/main/java/com/sevtinge/provision/utils/IKeyEvent.java rename to provision/src/main/java/com/sevtinge/provision/utils/IKeyEvent.java diff --git a/app/provision/src/main/java/com/sevtinge/provision/utils/IOnFocusListener.java b/provision/src/main/java/com/sevtinge/provision/utils/IOnFocusListener.java similarity index 100% rename from app/provision/src/main/java/com/sevtinge/provision/utils/IOnFocusListener.java rename to provision/src/main/java/com/sevtinge/provision/utils/IOnFocusListener.java diff --git a/app/provision/src/main/java/com/sevtinge/provision/utils/IProvisionAnim.java b/provision/src/main/java/com/sevtinge/provision/utils/IProvisionAnim.java similarity index 100% rename from app/provision/src/main/java/com/sevtinge/provision/utils/IProvisionAnim.java rename to provision/src/main/java/com/sevtinge/provision/utils/IProvisionAnim.java diff --git a/app/provision/src/main/java/com/sevtinge/provision/utils/ProvisionAnimHelper.java b/provision/src/main/java/com/sevtinge/provision/utils/ProvisionAnimHelper.java similarity index 100% rename from app/provision/src/main/java/com/sevtinge/provision/utils/ProvisionAnimHelper.java rename to provision/src/main/java/com/sevtinge/provision/utils/ProvisionAnimHelper.java diff --git a/app/provision/src/main/res/drawable/provision_basic_settings.xml b/provision/src/main/res/drawable/provision_basic_settings.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_basic_settings.xml rename to provision/src/main/res/drawable/provision_basic_settings.xml diff --git a/app/provision/src/main/res/drawable/provision_logo_image.xml b/provision/src/main/res/drawable/provision_logo_image.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_logo_image.xml rename to provision/src/main/res/drawable/provision_logo_image.xml diff --git a/app/provision/src/main/res/drawable/provision_logo_image_bg.webp b/provision/src/main/res/drawable/provision_logo_image_bg.webp similarity index 100% rename from app/provision/src/main/res/drawable/provision_logo_image_bg.webp rename to provision/src/main/res/drawable/provision_logo_image_bg.webp diff --git a/app/provision/src/main/res/drawable/provision_logo_image_lite.xml b/provision/src/main/res/drawable/provision_logo_image_lite.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_logo_image_lite.xml rename to provision/src/main/res/drawable/provision_logo_image_lite.xml diff --git a/app/provision/src/main/res/drawable/provision_picker_btn_radio.xml b/provision/src/main/res/drawable/provision_picker_btn_radio.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_picker_btn_radio.xml rename to provision/src/main/res/drawable/provision_picker_btn_radio.xml diff --git a/app/provision/src/main/res/drawable/provision_service_state.xml b/provision/src/main/res/drawable/provision_service_state.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_service_state.xml rename to provision/src/main/res/drawable/provision_service_state.xml diff --git a/app/provision/src/main/res/drawable/provision_terms.xml b/provision/src/main/res/drawable/provision_terms.xml similarity index 100% rename from app/provision/src/main/res/drawable/provision_terms.xml rename to provision/src/main/res/drawable/provision_terms.xml diff --git a/app/provision/src/main/res/raw/mesh_fragment_shader.glsl b/provision/src/main/res/raw/mesh_fragment_shader.glsl similarity index 100% rename from app/provision/src/main/res/raw/mesh_fragment_shader.glsl rename to provision/src/main/res/raw/mesh_fragment_shader.glsl diff --git a/app/provision/src/main/res/raw/mesh_vertex_shader.glsl b/provision/src/main/res/raw/mesh_vertex_shader.glsl similarity index 100% rename from app/provision/src/main/res/raw/mesh_vertex_shader.glsl rename to provision/src/main/res/raw/mesh_vertex_shader.glsl diff --git a/app/provision/src/main/res/raw/vertex_shader.glsl b/provision/src/main/res/raw/vertex_shader.glsl similarity index 100% rename from app/provision/src/main/res/raw/vertex_shader.glsl rename to provision/src/main/res/raw/vertex_shader.glsl diff --git a/settings.gradle.kts b/settings.gradle.kts index 1e1719cf3f..eab79dcc64 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,9 +18,11 @@ dependencyResolutionManagement { maven("https://api.xposed.info") google() mavenCentral() + flatDir { + dirs("provision/libs") + } } } rootProject.name = "HyperCeiler" -include(":app", ":hidden-api", ":app:processor") -include(":app:provision") \ No newline at end of file +include(":app", "provision", "processor", "hidden-api") \ No newline at end of file diff --git a/src/main/java/com/hchen/database/HookBase.java b/src/main/java/com/hchen/database/HookBase.java new file mode 100644 index 0000000000..375360d11a --- /dev/null +++ b/src/main/java/com/hchen/database/HookBase.java @@ -0,0 +1,52 @@ +/* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2025 HyperCeiler Contributions + */ +package com.hchen.database; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author 焕晨HChen + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface HookBase { + /* + * 目标作用域 + * */ + String targetPackage(); + + /* + * 目标安卓版本 + * */ + int targetSdk() default -1; + + /* + * 目标 ROM 版本 + * */ + float targetOSVersion() default -1F; + + /* + * 是否是 pad 专属 + * 0 通用,1 Pad,2 手机 + * */ + int isPad() default 0; +} diff --git a/src/main/java/com/hchen/database/HookBaseProcessor.java b/src/main/java/com/hchen/database/HookBaseProcessor.java new file mode 100644 index 0000000000..4fb99e069e --- /dev/null +++ b/src/main/java/com/hchen/database/HookBaseProcessor.java @@ -0,0 +1,164 @@ +/* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2025 HyperCeiler Contributions + */ +package com.hchen.database; + +import com.google.auto.service.AutoService; + +import java.io.IOException; +import java.io.Writer; +import java.util.Set; +import java.util.function.Consumer; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +/** + * @author 焕晨HChen + */ +@AutoService(Processor.class) +@SupportedAnnotationTypes("com.hchen.database.HookBase") +@SupportedSourceVersion(SourceVersion.RELEASE_21) +public class HookBaseProcessor extends AbstractProcessor { + int count = 0; + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + ++count; + if (count > 1) return true; + delayedOutput(); + try (Writer writer = processingEnv.getFiler().createSourceFile("com.sevtinge.hyperceiler.module.base.DataBase").openWriter()) { + writer.write(""" + /* + * This file is part of HyperCeiler. + + * HyperCeiler is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + + * Copyright (C) 2023-2025 HyperCeiler Contributions + */ + package com.sevtinge.hyperceiler.module.base; + + import java.util.HashMap; + + /** + * 注解处理器自动生成的 Map 图 + * + * @author 焕晨HChen + */ + public class DataBase { + public String mTargetPackage; + public int mTargetSdk; + public float mTargetOSVersion; + public int isPad; + + public DataBase(String targetPackage, int targetSdk, float targetOSVersion, int isPad){ + this.mTargetPackage = targetPackage; + this.mTargetSdk = targetSdk; + this.mTargetOSVersion = targetOSVersion; + this.isPad = isPad; + } + + public static HashMap get() { + HashMap dataMap = new HashMap<>(); + """); + roundEnv.getElementsAnnotatedWith(HookBase.class).forEach(new Consumer() { + @Override + public void accept(Element element) { + String fullClassName = null; + if (element instanceof TypeElement typeElement) { + fullClassName = typeElement.getQualifiedName().toString(); + // System.out.println("Full class name: " + fullClassName); + } + if (fullClassName == null) { + System.out.println("W: Full class name is null!!!"); + } + HookBase hookBase = element.getAnnotation(HookBase.class); + String targetPackage = hookBase.targetPackage(); + int targetSdk = hookBase.targetSdk(); + float targetOSVersion = hookBase.targetOSVersion(); + int isPad = hookBase.isPad(); + try { + writer.write(" "); + writer.write("dataMap.put(\"" + fullClassName + "\", new DataBase(\"" + targetPackage + "\", " + + targetSdk + ", " + targetOSVersion + "F, " + isPad + "));\n"); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + writer.write(""" + return dataMap; + } + } + """); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + /* + ________ ___ ___ ________ ________ ___ ___ + |\ _____\|\ \|\ \ |\ __ \ |\ __ \ |\ \ / /| + \ \ \__/ \ \ \\\ \\ \ \|\ \\ \ \|\ \ \ \ \/ / / + \ \ __\ \ \ \\\ \\ \ _ _\\ \ _ _\ \ \ / / + \ \ \_| \ \ \\\ \\ \ \\ \|\ \ \\ \| \/ / / + \ \__\ \ \_______\\ \__\\ _\ \ \__\\ _\ __/ / / + \|__| \|_______| \|__|\|__| \|__|\|__||\___/ / + \|___|/ + * */ + private void delayedOutput() { + final String RESET = "\033[0m"; // Text Reset + final String RED = "\033[0;31m"; // RED + final String GREEN = "\033[0;32m"; // GREEN + final String YELLOW = "\033[0;33m"; // YELLOW + final String BLUE = "\033[0;34m"; // BLUE + final String PURPLE = "\033[0;35m"; // PURPLE + final String CYAN = "\033[0;36m"; // CYAN + final String WHITE = "\033[0;37m"; // WHITE + System.out.println(BLUE + " " + RESET); + System.out.println(BLUE + " ________ ___ ___ ________ ________ ___ ___ " + RESET); + System.out.println(BLUE + "|\\ _____\\|\\ \\|\\ \\ |\\ __ \\ |\\ __ \\ |\\ \\ / /|" + RESET); + System.out.println(BLUE + "\\ \\ \\__/ \\ \\ \\\\\\ \\\\ \\ \\|\\ \\\\ \\ \\|\\ \\ \\ \\ \\/ / /" + RESET); + System.out.println(BLUE + " \\ \\ __\\ \\ \\ \\\\\\ \\\\ \\ _ _\\\\ \\ _ _\\ \\ \\ / / " + RESET); + System.out.println(BLUE + " \\ \\ \\_| \\ \\ \\\\\\ \\\\ \\ \\\\ \\|\\ \\ \\\\ \\| \\/ / / " + RESET); + System.out.println(BLUE + " \\ \\__\\ \\ \\_______\\\\ \\__\\\\ _\\ \\ \\__\\\\ _\\ __/ / / " + RESET); + System.out.println(BLUE + " \\|__| \\|_______| \\|__|\\|__| \\|__|\\|__||\\___/ / " + RESET); + System.out.println(BLUE + " \\|___|/ " + RESET); + System.out.println(BLUE + " " + RESET); + System.out.println(BLUE + " Code By 焕晨HChen " + RESET); // 别改谢谢 + } + +} \ No newline at end of file