├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── android.yml ├── .gitignore ├── .idea └── icon.png ├── LICENSE ├── MiuiHomeR.png ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── dict.txt ├── libs │ ├── animation-release.aar │ ├── annotation-release.aar │ ├── appcompat-release.aar │ ├── appcompat-resources-release.aar │ ├── blur-release.aar │ ├── core-release.aar │ ├── haptic-release.aar │ ├── internal-release.aar │ ├── os-release.aar │ ├── preference-release.aar │ ├── recyclerview-release.aar │ ├── smooth-release.aar │ └── springback-release.aar ├── proguard-log.pro ├── proguard-rules.pro └── src │ ├── .gitignore │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── xposed_init │ ├── java │ └── com │ │ ├── yuk │ │ └── miuiHomeR │ │ │ ├── Application.kt │ │ │ ├── MainHook.kt │ │ │ ├── hook │ │ │ ├── AllAppsContainerViewBlur.kt │ │ │ ├── AllowMoveAllWidgetToMinus.kt │ │ │ ├── AlwaysBlurWallpaper.kt │ │ │ ├── AlwaysShowMiuiWidget.kt │ │ │ ├── AlwaysShowStatusClock.kt │ │ │ ├── AnimDurationRatio.kt │ │ │ ├── AppDrawer.kt │ │ │ ├── BaseHook.kt │ │ │ ├── BigIconCorner.kt │ │ │ ├── BlurLevel.kt │ │ │ ├── BlurRadius.kt │ │ │ ├── CloseFolderWhenLaunchedApp.kt │ │ │ ├── DisableRecentViewWallpaperDarken.kt │ │ │ ├── Dock.kt │ │ │ ├── DoubleTapController.kt │ │ │ ├── DoubleTapToSleep.kt │ │ │ ├── EnableBigFolderIconBlur.kt │ │ │ ├── EnableBlurWhenOpenFolder.kt │ │ │ ├── EnableFolderIconBlur.kt │ │ │ ├── FoldDeviceDock.kt │ │ │ ├── FolderAnim.kt │ │ │ ├── FolderColumnsCount.kt │ │ │ ├── FolderVerticalPadding.kt │ │ │ ├── HapticFeedback.kt │ │ │ ├── HideSeekPoint.kt │ │ │ ├── HideStatusBarWhenEnterRecent.kt │ │ │ ├── HideWidgetTitles.kt │ │ │ ├── HomeSettings.kt │ │ │ ├── IconTitleColor.kt │ │ │ ├── IconTitleScrolling.kt │ │ │ ├── IconTitleSize.kt │ │ │ ├── InfiniteScroll.kt │ │ │ ├── OverlapMode.kt │ │ │ ├── Recent.kt │ │ │ ├── RemoveCardAnim.kt │ │ │ ├── ResourcesHook.kt │ │ │ ├── SetDeviceLevel.kt │ │ │ ├── ShortcutBlur.kt │ │ │ ├── ShortcutItemCount.kt │ │ │ ├── ShortcutSmallWindow.kt │ │ │ ├── ShowDockIconTitle.kt │ │ │ ├── TaskViewHorizontal.kt │ │ │ ├── TaskViewVertical.kt │ │ │ ├── UnlockAnim.kt │ │ │ └── UnlockHotseatIcon.kt │ │ │ ├── provider │ │ │ └── SharedPrefsProvider.kt │ │ │ ├── ui │ │ │ ├── AboutActivity.kt │ │ │ ├── AppDrawerActivity.kt │ │ │ ├── DockActivity.kt │ │ │ ├── FolderActivity.kt │ │ │ ├── HomeActivity.kt │ │ │ ├── MainActivity.kt │ │ │ ├── OtherActivity.kt │ │ │ ├── RecentActivity.kt │ │ │ ├── SettingsActivity.kt │ │ │ ├── WidgetActivity.kt │ │ │ └── base │ │ │ │ ├── BaseAppCompatActivity.kt │ │ │ │ ├── BasePreferenceFragment.kt │ │ │ │ └── SubFragment.kt │ │ │ ├── utils │ │ │ ├── AppManager.java │ │ │ ├── BackupUtils.kt │ │ │ ├── Helpers.kt │ │ │ ├── PrefsMap.java │ │ │ ├── PrefsUtils.kt │ │ │ ├── ResourcesHookData.kt │ │ │ ├── ResourcesHookMap.kt │ │ │ └── ktx │ │ │ │ ├── AppUtil.kt │ │ │ │ └── KotlinXposedHelper.kt │ │ │ └── view │ │ │ └── CircleImageView.java │ │ └── zhenxiang │ │ └── blur │ │ ├── BackgroundBlurDrawableExtensions.kt │ │ ├── BlurFrameLayout.kt │ │ ├── BlurLinearLayout.kt │ │ ├── SystemBlurController.kt │ │ ├── ViewExtensions.kt │ │ └── model │ │ └── CornerRadius.kt │ └── res │ ├── drawable-440dpi │ ├── ic_moralnorm.webp │ └── ic_yukonga.webp │ ├── drawable │ ├── ic_launcher_background.xml │ ├── ic_launcher_foreground.xml │ ├── ic_settings.xml │ ├── ic_task_small_window_dark.xml │ └── ic_task_small_window_light.xml │ ├── layout │ ├── activity_about.xml │ ├── activity_main.xml │ └── preference_round_layout.xml │ ├── mipmap-anydpi-v26 │ └── ic_launcher.xml │ ├── values-af │ └── strings.xml │ ├── values-ar │ └── strings.xml │ ├── values-ca │ └── strings.xml │ ├── values-cs │ └── strings.xml │ ├── values-da │ └── strings.xml │ ├── values-de │ └── strings.xml │ ├── values-el │ └── strings.xml │ ├── values-es │ └── strings.xml │ ├── values-fa │ └── strings.xml │ ├── values-fi │ └── strings.xml │ ├── values-fr │ └── strings.xml │ ├── values-he │ └── strings.xml │ ├── values-hu │ └── strings.xml │ ├── values-id │ └── strings.xml │ ├── values-it │ └── strings.xml │ ├── values-ja │ └── strings.xml │ ├── values-ka │ └── strings.xml │ ├── values-ko │ └── strings.xml │ ├── values-night │ └── colors.xml │ ├── values-nl │ └── strings.xml │ ├── values-no │ └── strings.xml │ ├── values-pl │ └── strings.xml │ ├── values-pt-rBR │ └── strings.xml │ ├── values-pt │ └── strings.xml │ ├── values-ro │ └── strings.xml │ ├── values-ru-rRU │ └── strings.xml │ ├── values-ru │ └── strings.xml │ ├── values-sr │ └── strings.xml │ ├── values-sv │ └── strings.xml │ ├── values-th │ └── strings.xml │ ├── values-tr │ └── strings.xml │ ├── values-uk │ └── strings.xml │ ├── values-uz │ └── strings.xml │ ├── values-vi │ └── strings.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rHK │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ ├── values │ ├── arrays.xml │ ├── attrs.xml │ ├── colors.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── prefs_about.xml │ ├── prefs_app_drawer.xml │ ├── prefs_dock.xml │ ├── prefs_folder.xml │ ├── prefs_home.xml │ ├── prefs_main.xml │ ├── prefs_other.xml │ ├── prefs_recent.xml │ ├── prefs_settings.xml │ └── prefs_widget.xml ├── build.gradle.kts ├── crowdin.yml ├── dependabot.yml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── hidden-api ├── .gitignore ├── build.gradle.kts ├── proguard-rules.pro └── src │ └── main │ └── java │ ├── android │ └── view │ │ └── ViewRootImpl.java │ └── com │ └── android │ └── internal │ └── graphics │ └── drawable │ └── BackgroundBlurDrawable.java └── settings.gradle.kts /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gradle" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | paths-ignore: 7 | - 'README.md' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3.2.0 15 | 16 | - name: Setup JDK 17 17 | uses: actions/setup-java@v3.9.0 18 | with: 19 | java-version: '17' 20 | distribution: 'adopt' 21 | 22 | - name: Cache Gradle Dependencies 23 | uses: actions/cache@v3.2.2 24 | with: 25 | path: | 26 | ~/.gradle/caches 27 | ~/.gradle/wrapper 28 | !~/.gradle/caches/build-cache-* 29 | key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }} 30 | restore-keys: gradle-deps 31 | 32 | - name: Cache Gradle Build 33 | uses: actions/cache@v3.2.2 34 | with: 35 | path: | 36 | ~/.gradle/caches/build-cache-* 37 | ~/.gradle/buildOutputCleanup/cache.properties 38 | key: gradle-builds-core-${{ github.sha }} 39 | restore-keys: gradle-builds 40 | 41 | - name: Build with Gradle 42 | run: | 43 | echo ${{ secrets.SIGNING_KEY }} | base64 -d > keystore.jks 44 | bash ./gradlew assemble 45 | env: 46 | KEYSTORE_PATH: "../keystore.jks" 47 | KEYSTORE_PASS: ${{ secrets.KEY_STORE_PASSWORD }} 48 | KEY_ALIAS: ${{ secrets.ALIAS }} 49 | KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} 50 | 51 | - name: Upload Release APK 52 | uses: actions/upload-artifact@v3 53 | with: 54 | name: MiuiHomeR_Release 55 | path: "app/build/outputs/apk/release/*.apk" 56 | 57 | - name: Upload Debug APK 58 | uses: actions/upload-artifact@v3 59 | with: 60 | name: MiuiHomeR_Debug 61 | path: "app/build/outputs/apk/debug/*.apk" 62 | 63 | - name: Find apk 64 | run: | 65 | echo "RELEASE=$(find 'app/build/outputs/apk/release' -name '*.apk')" >> $GITHUB_ENV 66 | echo "DEBUG=$(find 'app/build/outputs/apk/debug' -name '*.apk')" >> $GITHUB_ENV 67 | 68 | - name: Post to channel 69 | if: contains(github.event.head_commit.message, '[skip post]') == false 70 | env: 71 | CHANNEL_ID: ${{ secrets.CHANNEL_ID }} 72 | BOT_TOKEN: ${{ secrets.BOT_TOKEN }} 73 | RELEASE: ${{ env.RELEASE }} 74 | DEBUG: ${{ env.DEBUG }} 75 | COMMIT_MESSAGE: |+ 76 | New push in Github\! 77 | ``` 78 | ${{ github.event.head_commit.message }} 79 | ``` 80 | run: | 81 | ESCAPED=`python3 -c 'import json,os,urllib.parse; print(urllib.parse.quote(json.dumps(os.environ["COMMIT_MESSAGE"])))'` 82 | curl -v "https://api.telegram.org/bot${BOT_TOKEN}/sendMediaGroup?chat_id=${CHANNEL_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Frelease%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fdebug%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A${ESCAPED}%7D%5D" -F release="@$RELEASE" -F debug="@$DEBUG" 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | *.aab 5 | 6 | # Files for the ART/Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | out/ 16 | 17 | # Gradle files 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # IntelliJ 37 | *.iml 38 | .idea/ 39 | 40 | # Keystore files 41 | # Uncomment the following lines if you do not want to check your keystore files in. 42 | #*.jks 43 | #*.keystore 44 | 45 | # External native build folder generated in Android Studio 2.2 and later 46 | .externalNativeBuild 47 | 48 | # Google Services (e.g. APIs or Firebase) 49 | google-services.json 50 | 51 | # Freeline 52 | freeline.py 53 | freeline/ 54 | freeline_project_description.json 55 | 56 | # fastlane 57 | fastlane/report.xml 58 | fastlane/Preview.html 59 | fastlane/screenshots 60 | fastlane/test_output 61 | fastlane/readme.md -------------------------------------------------------------------------------- /.idea/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/.idea/icon.png -------------------------------------------------------------------------------- /MiuiHomeR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/MiuiHomeR.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

MiuiHomeR

4 | 5 | Make MiuiHome Great Again - Xposed 6 | 7 | [![Android CI](https://github.com/qqlittleice/MiuiHome_R/actions/workflows/android.yml/badge.svg)](https://github.com/qqlittleice/MiuiHome_R/actions/workflows/android.yml) 8 | [![Crowdin](https://badges.crowdin.net/miuihomer/localized.svg)](https://crowdin.com/project/miuihomer) 9 | [![Chat](https://img.shields.io/badge/Telegram-Chat-blue.svg?logo=telegram)](https://t.me/MiuiHome_Xposed) 10 | [![Release](https://img.shields.io/github/v/release/Xposed-Modules-Repo/com.yuk.miuihomer?label=release)](https://github.com/Xposed-Modules-Repo/com.yuk.miuihomeR/releases/latest) 11 | 12 | ![Launcher](https://gcore.jsdelivr.net/gh/qqlittleice/MiuiHome_R@main/MiuiHomeR.png) 13 | 14 |
15 | 16 | ----- 17 | 18 | ## Translation 19 | 20 | [Crowdin](https://crowdin.com/project/miuihomer/invite?h=1b68e3fdf40ff94a42d8409affcb24f71535875) 21 | 22 | ## Creates 23 | 24 |
25 | 26 | - [AndroidHiddenApiBypass](https://github.com/LSPosed/AndroidHiddenApiBypass) 27 | -- [Apache License 2.0](https://github.com/LSPosed/AndroidHiddenApiBypass/blob/main/LICENSE) 28 | - [EzXHelper](https://github.com/KyuubiRan/EzXHelper) 29 | -- [Apache License 2.0](https://github.com/KyuubiRan/EzXHelper/blob/master/LICENSE) 30 | - [XposedBridge](https://github.com/rovo89/XposedBridge) 31 | -- [Apache License 2.0](https://github.com/rovo89/XposedBridge/blob/art/NOTICE.txt) 32 | 33 | - [AndroidSystemBlur](https://github.com/Lucchetto/AndroidSystemBlur) 34 | -- [GNU General Public License v2.0](https://github.com/Lucchetto/AndroidSystemBlur/blob/master/LICENSE.txt) 35 | 36 | - [BiliRoaming](https://github.com/yujincheng08/BiliRoaming) 37 | -- [GNU General Public License v3.0](https://github.com/yujincheng08/BiliRoaming/blob/master/LICENSE) 38 | - [CustoMIUIzer](https://code.highspec.ru/Mikanoshi/CustoMIUIzer) 39 | -- [GNU General Public License v3.0](https://code.highspec.ru/Mikanoshi/CustoMIUIzer/src/branch/master/LICENSE) 40 | - [LSPosed](https://github.com/LSPosed/LSPosed) 41 | -- [GNU General Public License v3.0](https://github.com/LSPosed/LSPosed/blob/master/LICENSE) 42 | 43 | - [MIUIDock](https://github.com/ouhoukyo/MIUIDock) 44 | -- [MIT](https://github.com/ouhoukyo/MIUIDock/blob/master/LICENSE) 45 | - [MIDock](https://github.com/lamprose/MIDock) 46 | -- [MIT](https://github.com/lamprose/MIDock/blob/master/LICENSE) 47 | - [WINI](https://github.com/ouhoukyo/WINI) 48 | -- [MIT](https://github.com/ouhoukyo/WINI/blob/main/LICENSE) 49 | 50 | - [QNotified](https://github.com/ferredoxin/QNotified) 51 | -- [License v2](https://github.com/qwq233/License/blob/master/v2/LICENSE.md) 52 | 53 |
54 | 55 | ## License 56 | 57 | [GNU General Public License v3.0](LICENSE) 58 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /release 3 | /debug 4 | -------------------------------------------------------------------------------- /app/libs/animation-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/animation-release.aar -------------------------------------------------------------------------------- /app/libs/annotation-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/annotation-release.aar -------------------------------------------------------------------------------- /app/libs/appcompat-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/appcompat-release.aar -------------------------------------------------------------------------------- /app/libs/appcompat-resources-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/appcompat-resources-release.aar -------------------------------------------------------------------------------- /app/libs/blur-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/blur-release.aar -------------------------------------------------------------------------------- /app/libs/core-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/core-release.aar -------------------------------------------------------------------------------- /app/libs/haptic-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/haptic-release.aar -------------------------------------------------------------------------------- /app/libs/internal-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/internal-release.aar -------------------------------------------------------------------------------- /app/libs/os-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/os-release.aar -------------------------------------------------------------------------------- /app/libs/preference-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/preference-release.aar -------------------------------------------------------------------------------- /app/libs/recyclerview-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/recyclerview-release.aar -------------------------------------------------------------------------------- /app/libs/smooth-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/smooth-release.aar -------------------------------------------------------------------------------- /app/libs/springback-release.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/libs/springback-release.aar -------------------------------------------------------------------------------- /app/proguard-log.pro: -------------------------------------------------------------------------------- 1 | ########################################################################################################## 2 | # 作者:Sollyu 3 | # 日期:2020-11-02 4 | # 内容:发布版本移除日志,kotlin编译时带的而外信息,增强反调试难度 5 | # 使用:proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro' 6 | ########################################################################################################## 7 | 8 | ########################################################################################################## 9 | # 删除安卓日志 10 | -assumenosideeffects class android.util.Log { 11 | public static *** d(...); 12 | public static *** v(...); 13 | public static *** w(...); 14 | public static *** e(...); 15 | } 16 | 17 | ########################################################################################################## 18 | # 删除Kotlin编译时可能生成显示变量的方法 19 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics { 20 | public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String); 21 | public static void checkFieldIsNotNull(java.lang.Object, java.lang.String); 22 | public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String); 23 | public static void checkNotNull(java.lang.Object); 24 | public static void checkNotNull(java.lang.Object, java.lang.String); 25 | public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String); 26 | public static void checkNotNullParameter(java.lang.Object, java.lang.String); 27 | public static void checkParameterIsNotNull(java.lang.Object, java.lang.String); 28 | public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String); 29 | public static void throwUninitializedPropertyAccessException(java.lang.String); 30 | } 31 | 32 | ########################################################################################################## 33 | # 会暴露变量名称 34 | -assumenosideeffects class java.util.Objects { 35 | public static java.lang.Object requireNonNull(java.lang.Object, java.lang.String); 36 | } 37 | 38 | ########################################################################################################## 39 | # 删除slf4j的日志输出 40 | -assumenosideeffects interface org.slf4j.Logger { 41 | public void trace(...); 42 | public void debug(...); 43 | public void info(...); 44 | public void warn(...); 45 | public void error(...); 46 | 47 | public boolean isTraceEnabled(...); 48 | public boolean isDebugEnabled(...); 49 | public boolean isWarnEnabled(...); 50 | } 51 | 52 | -assumenosideeffects class org.slf4j.LoggerFactory { 53 | public static ** getLogger(...); 54 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | -repackageclasses "余空" 24 | -obfuscationdictionary dict.txt 25 | -classobfuscationdictionary dict.txt 26 | -packageobfuscationdictionary dict.txt 27 | 28 | -keep class com.yuk.miuiHomeR.MainHook { 29 | (); 30 | } 31 | 32 | -assumenosideeffects class kotlin.jvm.internal.Intrinsics { 33 | public static void check*(...); 34 | public static void throw*(...); 35 | } 36 | 37 | -keep class moralnorm.** {*;} 38 | -keep public class * extends moralnorm.** 39 | 40 | -keepclasseswithmembers class * { 41 | public (android.content.Context, android.util.AttributeSet); 42 | } 43 | 44 | -allowaccessmodification 45 | -overloadaggressively -------------------------------------------------------------------------------- /app/src/.gitignore: -------------------------------------------------------------------------------- 1 | /androidTest 2 | /test -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 41 | 42 | 45 | 46 | 49 | 50 | 53 | 54 | 57 | 58 | 61 | 62 | 65 | 66 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 84 | 85 | 89 | 92 | 93 | 94 | 97 | 100 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.yuk.miuiHomeR.MainHook -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/Application.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR 2 | 3 | import android.content.Context 4 | import com.yuk.miuiHomeR.utils.PrefsUtils 5 | import com.yuk.miuiHomeR.utils.PrefsUtils.getSharedPrefs 6 | import com.yuk.miuiHomeR.utils.ktx.setLocale 7 | import java.util.Locale 8 | 9 | class Application : android.app.Application() { 10 | 11 | override fun attachBaseContext(base: Context?) { 12 | PrefsUtils.mSharedPreferences = base?.let { getSharedPrefs(it, false) } 13 | val locale: String? = PrefsUtils.mSharedPreferences?.getString("prefs_key_settings_language", "SYSTEM") 14 | if (locale != null) { 15 | if (base != null) 16 | super.attachBaseContext(setLocale(base, Locale.forLanguageTag(locale))) 17 | } else super.attachBaseContext(base) 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AllAppsContainerViewBlur.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.os.Build 4 | import android.view.View 5 | import android.widget.FrameLayout 6 | import android.widget.RelativeLayout 7 | import android.widget.ViewSwitcher 8 | import androidx.annotation.RequiresApi 9 | import com.github.kyuubiran.ezxhelper.utils.findMethod 10 | import com.github.kyuubiran.ezxhelper.utils.hookAfter 11 | import com.yuk.miuiHomeR.mPrefsMap 12 | import com.yuk.miuiHomeR.utils.ktx.findClass 13 | import com.yuk.miuiHomeR.utils.ktx.getCornerRadiusTop 14 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 15 | import com.zhenxiang.blur.BlurFrameLayout 16 | import com.zhenxiang.blur.model.CornersRadius 17 | 18 | @RequiresApi(Build.VERSION_CODES.S) 19 | object AllAppsContainerViewBlur : BaseHook() { 20 | override fun init() { 21 | 22 | if (!mPrefsMap.getBoolean("home_all_apps_blur")) return 23 | findMethod("com.miui.home.launcher.allapps.BaseAllAppsContainerView".findClass(), true) { 24 | name == "onFinishInflate" 25 | }.hookAfter { hookParam -> 26 | val mCategoryContainer = hookParam.thisObject.getObjectField("mCategoryContainer") as ViewSwitcher 27 | val appsView = mCategoryContainer.parent as RelativeLayout 28 | val blur = BlurFrameLayout(mCategoryContainer.context) 29 | val radius = getCornerRadiusTop().toFloat() 30 | blur.blurController.apply { 31 | cornerRadius = CornersRadius.custom(radius, radius, 0f, 0f) 32 | } 33 | val view = View(mCategoryContainer.context) 34 | blur.addView(view) 35 | (view.layoutParams as FrameLayout.LayoutParams).apply { 36 | width = FrameLayout.LayoutParams.MATCH_PARENT 37 | height = FrameLayout.LayoutParams.MATCH_PARENT 38 | } 39 | appsView.addView(blur, 0) 40 | findMethod("com.miui.home.launcher.allapps.BaseAllAppsContainerView".findClass(), true) { 41 | name == "onResume" 42 | }.hookAfter { 43 | blur.refreshDrawableState() 44 | } 45 | } 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AllowMoveAllWidgetToMinus.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.getObject 5 | import com.github.kyuubiran.ezxhelper.utils.getObjectOrNull 6 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 7 | import com.github.kyuubiran.ezxhelper.utils.invokeMethodAuto 8 | import com.yuk.miuiHomeR.mPrefsMap 9 | import com.yuk.miuiHomeR.utils.ktx.callMethod 10 | 11 | object AllowMoveAllWidgetToMinus : BaseHook() { 12 | override fun init() { 13 | 14 | if (!mPrefsMap.getBoolean("home_widget_to_minus")) return 15 | try { 16 | findMethod("com.miui.home.launcher.widget.MIUIWidgetHelper") { 17 | name == "canDragToPa" && parameterCount == 2 18 | }.hookBefore { 19 | val dragInfo = it.args[1].invokeMethodAuto("getDragInfo") 20 | val i = dragInfo?.getObject("spanX") 21 | val launcherCallbacks = it.args[0].invokeMethodAuto("getLauncherCallbacks") 22 | val dragController = it.args[0].invokeMethodAuto("getDragController") 23 | val isDraggingFromAssistant = dragController?.callMethod("isDraggingFromAssistant") as Boolean 24 | val isDraggingToAssistant = dragController.callMethod("isDraggingToAssistant") as Boolean 25 | it.result = launcherCallbacks != null && !isDraggingFromAssistant && !isDraggingToAssistant && i != 1 26 | } 27 | } catch (e: Exception) { 28 | findMethod("com.miui.home.launcher.Workspace") { 29 | name == "canDragToPa" 30 | }.hookBefore { 31 | val currentDragObject = it.thisObject.getObjectOrNull("mDragController")?.invokeMethodAuto("getCurrentDragObject") 32 | val dragInfo = currentDragObject?.invokeMethodAuto("getDragInfo") 33 | val i = dragInfo?.getObject("spanX") 34 | val launcherCallbacks = it.thisObject.getObjectOrNull("mLauncher")?.invokeMethodAuto("getLauncherCallbacks") 35 | val isDraggingFromAssistant = it.thisObject.getObjectOrNull("mDragController")?.callMethod("isDraggingFromAssistant") as Boolean 36 | val isDraggingToAssistant = it.thisObject.getObjectOrNull("mDragController")?.callMethod("isDraggingToAssistant") as Boolean 37 | it.result = launcherCallbacks != null && !isDraggingFromAssistant && !isDraggingToAssistant && i != 1 38 | } 39 | } 40 | 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AlwaysBlurWallpaper.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object AlwaysBlurWallpaper : BaseHook() { 8 | override fun init() { 9 | 10 | if (!mPrefsMap.getBoolean("home_blur_wallpaper")) return 11 | val value = mPrefsMap.getInt("home_blur_radius", 100) 12 | findMethod("com.miui.home.launcher.common.BlurUtils") { 13 | name == "fastBlur" && parameterCount == 4 14 | }.hookBefore { 15 | it.args[0] = value.toFloat() / 100 16 | it.args[2] = true 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AlwaysShowMiuiWidget.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookAfter 5 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 6 | import com.github.kyuubiran.ezxhelper.utils.hookMethod 7 | import com.github.kyuubiran.ezxhelper.utils.putObject 8 | import com.yuk.miuiHomeR.mPrefsMap 9 | import de.robv.android.xposed.XC_MethodHook 10 | 11 | object AlwaysShowMiuiWidget : BaseHook() { 12 | override fun init() { 13 | 14 | if (!mPrefsMap.getBoolean("home_widget_miui")) return 15 | var hook1: XC_MethodHook.Unhook? = null 16 | var hook2: XC_MethodHook.Unhook? = null 17 | try { 18 | findMethod("com.miui.home.launcher.widget.WidgetsVerticalAdapter") { 19 | name == "buildAppWidgetsItems" 20 | } 21 | } catch (e: Exception) { 22 | findMethod("com.miui.home.launcher.widget.BaseWidgetsVerticalAdapter") { 23 | name == "buildAppWidgetsItems" 24 | } 25 | }.hookMethod { 26 | before { 27 | hook1 = findMethod("com.miui.home.launcher.widget.MIUIAppWidgetInfo") { 28 | name == "initMiuiAttribute" && parameterCount == 1 29 | }.hookAfter { 30 | it.thisObject.putObject("isMIUIWidget", false) 31 | } 32 | hook2 = findMethod("com.miui.home.launcher.MIUIWidgetUtil") { 33 | name == "isMIUIWidgetSupport" 34 | }.hookBefore { 35 | it.result = false 36 | } 37 | } 38 | after { 39 | hook1?.unhook() 40 | hook2?.unhook() 41 | } 42 | } 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AlwaysShowStatusClock.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object AlwaysShowStatusClock : BaseHook() { 8 | override fun init() { 9 | 10 | if (!mPrefsMap.getBoolean("home_show_status_clock")) return 11 | try { 12 | findMethod("com.miui.home.launcher.Workspace") { 13 | name == "isScreenHasClockGadget" && parameterCount == 1 14 | } 15 | } catch (e: Exception) { 16 | findMethod("com.miui.home.launcher.Workspace") { 17 | name == "isScreenHasClockWidget" && parameterCount == 1 18 | } 19 | }.hookReturnConstant(false) 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AnimDurationRatio.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object AnimDurationRatio : BaseHook() { 8 | override fun init() { 9 | 10 | val value1 = mPrefsMap.getInt("home_anim_ratio", 150).toFloat() / 100f 11 | val value2 = mPrefsMap.getInt("home_anim_ratio_recent", 130).toFloat() / 100f 12 | findMethod("com.miui.home.recents.util.RectFSpringAnim") { 13 | name == "getModifyResponse" 14 | }.hookBefore { 15 | it.result = it.args[0] as Float * value1 16 | } 17 | 18 | findMethod("com.miui.home.launcher.common.DeviceLevelUtils") { 19 | name == "getDeviceLevelTransitionAnimRatio" 20 | }.hookBefore { 21 | it.result = value2 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/AppDrawer.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.view.View 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookAfter 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.callMethodAs 8 | import com.yuk.miuiHomeR.utils.ktx.findClass 9 | import com.yuk.miuiHomeR.utils.ktx.getObjectFieldAs 10 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 11 | 12 | object AppDrawer : BaseHook() { 13 | override fun init() { 14 | 15 | if (mPrefsMap.getBoolean("home_hide_category_all")) { 16 | try { 17 | findMethod("com.miui.home.launcher.allapps.category.BaseAllAppsCategoryListContainer") { 18 | name == "buildSortCategoryList" 19 | } 20 | } catch (e: Exception) { 21 | findMethod("com.miui.home.launcher.allapps.category.AllAppsCategoryListContainer") { 22 | name == "buildSortCategoryList" 23 | } 24 | }.hookAfter { 25 | val list = it.result as ArrayList<*> 26 | if (list.size > 1) { 27 | list.removeAt(0) 28 | it.result = list 29 | } 30 | } 31 | } 32 | 33 | if (mPrefsMap.getBoolean("home_hide_category_paging_edit")) { 34 | "com.miui.home.launcher.allapps.AllAppsGridAdapter".hookAfterMethod( 35 | "onBindViewHolder", "com.miui.home.launcher.allapps.AllAppsGridAdapter.ViewHolder".findClass(), Int::class.javaPrimitiveType 36 | ) { 37 | if (it.args[0].callMethodAs("getItemViewType") == 64) { 38 | it.args[0].getObjectFieldAs("itemView").visibility = View.INVISIBLE 39 | } 40 | } 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/BaseHook.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | abstract class BaseHook { 4 | var isInit: Boolean = false 5 | abstract fun init() 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/BigIconCorner.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 7 | 8 | object BigIconCorner : BaseHook() { 9 | override fun init() { 10 | 11 | if (!mPrefsMap.getBoolean("big_icon_corner")) return 12 | findMethod("com.miui.home.launcher.bigicon.BigIconUtil") { 13 | name == "getCroppedFromCorner" && parameterCount == 4 14 | }.hookBefore { 15 | it.args[0] = 2 16 | it.args[1] = 2 17 | } 18 | 19 | findMethod( 20 | "com.miui.home.launcher.maml.MaMlHostView" 21 | ) { 22 | name == "getCornerRadius" 23 | }.hookBefore { 24 | it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float 25 | } 26 | 27 | findMethod("com.miui.home.launcher.maml.MaMlHostView") { 28 | name == "computeRoundedCornerRadius" && parameterCount == 1 29 | }.hookBefore { 30 | it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float 31 | } 32 | 33 | findMethod("com.miui.home.launcher.LauncherAppWidgetHostView") { 34 | name == "computeRoundedCornerRadius" && parameterCount == 1 35 | }.hookBefore { 36 | it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float 37 | } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/BlurLevel.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.app.Activity 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 6 | import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant 7 | import com.yuk.miuiHomeR.mPrefsMap 8 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 9 | import com.yuk.miuiHomeR.utils.ktx.findClass 10 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllMethods 11 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 12 | 13 | object BlurLevel : BaseHook() { 14 | override fun init() { 15 | 16 | val blurLevel = mPrefsMap.getStringAsInt("recent_blur", 2) 17 | if (blurLevel == 4) { 18 | findMethod("com.miui.home.launcher.common.BlurUtils") { 19 | name == "getBlurType" 20 | }.hookReturnConstant(0) 21 | findMethod("com.miui.home.launcher.common.BlurUtils") { 22 | name == "isUseCompleteBlurOnDev" 23 | }.hookReturnConstant(false) 24 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") { 25 | it.result = true 26 | } 27 | } else { 28 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") { 29 | it.result = false 30 | } 31 | findMethod("com.miui.home.launcher.common.BlurUtils") { 32 | name == "getBlurType" 33 | }.hookBefore { 34 | when (blurLevel) { 35 | 0 -> it.result = 2 36 | 2 -> it.result = 1 37 | 3 -> it.result = 0 38 | } 39 | } 40 | findMethod("com.miui.home.launcher.common.BlurUtils") { 41 | name == "isUseCompleteBlurOnDev" 42 | }.hookBefore { 43 | when (blurLevel) { 44 | 1 -> it.result = true 45 | } 46 | } 47 | } 48 | if (blurLevel == 0 && mPrefsMap.getBoolean("complete_blur_fix")) { 49 | val blurClass = "com.miui.home.launcher.common.BlurUtils".findClass() 50 | val navStubViewClass = "com.miui.home.recents.NavStubView".findClass() 51 | val applicationClass = "com.miui.home.launcher.Application".findClass() 52 | navStubViewClass.hookAfterAllMethods("onTouchEvent") { 53 | val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity 54 | blurClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 500L) 55 | } 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/BlurRadius.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.loadClass 4 | import com.yuk.miuiHomeR.mPrefsMap 5 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeAllMethods 6 | 7 | object BlurRadius : BaseHook() { 8 | override fun init() { 9 | 10 | val value = mPrefsMap.getInt("home_blur_radius", 100).toFloat() / 100 11 | if (value == 1f) return 12 | val blurUtilsClass = loadClass("com.miui.home.launcher.common.BlurUtils") 13 | blurUtilsClass.hookBeforeAllMethods("fastBlur") { 14 | it.args[0] = it.args[0] as Float * value 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/CloseFolderWhenLaunchedApp.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.view.View 4 | import com.yuk.miuiHomeR.mPrefsMap 5 | import com.yuk.miuiHomeR.utils.ktx.callMethod 6 | import com.yuk.miuiHomeR.utils.ktx.getBooleanField 7 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 8 | 9 | object CloseFolderWhenLaunchedApp : BaseHook() { 10 | override fun init() { 11 | 12 | if (!mPrefsMap.getBoolean("home_close_folder")) return 13 | "com.miui.home.launcher.Launcher".hookAfterMethod( 14 | "launch", "com.miui.home.launcher.ShortcutInfo", View::class.java 15 | ) { 16 | val mHasLaunchedAppFromFolder = it.thisObject.getBooleanField("mHasLaunchedAppFromFolder") 17 | if (mHasLaunchedAppFromFolder) it.thisObject.callMethod("closeFolder") 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/DisableRecentViewWallpaperDarken.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 5 | import com.github.kyuubiran.ezxhelper.utils.putObject 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | 8 | object DisableRecentViewWallpaperDarken : BaseHook() { 9 | override fun init() { 10 | 11 | if (!mPrefsMap.getBoolean("home_disable_darken")) return 12 | findMethod("com.miui.home.recents.DimLayer") { 13 | name == "dim" && parameterCount == 3 14 | }.hookBefore { 15 | it.args[0] = 0.0f 16 | it.thisObject.putObject("mCurrentAlpha", 0.0f) 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/Dock.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import android.view.Gravity 6 | import android.view.View 7 | import android.widget.FrameLayout 8 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext 9 | import com.github.kyuubiran.ezxhelper.utils.hookAllConstructorAfter 10 | import com.yuk.miuiHomeR.mPrefsMap 11 | import com.yuk.miuiHomeR.utils.ktx.atLeastAndroidS 12 | import com.yuk.miuiHomeR.utils.ktx.callMethod 13 | import com.yuk.miuiHomeR.utils.ktx.dp2px 14 | import com.yuk.miuiHomeR.utils.ktx.findClass 15 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 16 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 17 | import com.zhenxiang.blur.BlurFrameLayout 18 | import com.zhenxiang.blur.model.CornersRadius 19 | import de.robv.android.xposed.XposedHelpers 20 | 21 | object Dock : BaseHook() { 22 | override fun init() { 23 | 24 | if (!mPrefsMap.getBoolean("dock_hook_enabled")) return 25 | var isShowEditPanel = false 26 | var isFolderShowing = false 27 | val launcherClass = "com.miui.home.launcher.Launcher".findClass() 28 | val launcherStateClass = "com.miui.home.launcher.LauncherState".findClass() 29 | val folderInfo = "com.miui.home.launcher.FolderInfo".findClass() 30 | val blurClass = "com.miui.home.launcher.common.BlurUtils".findClass() 31 | val mDockHeight = dp2px(mPrefsMap.getInt("home_dock_height", 98).toFloat()) 32 | val mDockMargin = dp2px(mPrefsMap.getInt("home_dock_margin", 10).toFloat()) 33 | val mDockBottomMargin = dp2px(mPrefsMap.getInt("home_dock_bottom_margin", 13).toFloat()) 34 | val mDockCorner = dp2px(mPrefsMap.getInt("home_dock_corner", 25).toFloat()) 35 | 36 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod( 37 | "calcHotSeatsMarginTop", Context::class.java, Boolean::class.javaPrimitiveType 38 | ) { 39 | it.result = dp2px(mPrefsMap.getInt("home_dock_top_margin", 20).toFloat()) 40 | } 41 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod( 42 | "getWorkspaceIndicatorMarginBottom" 43 | ) { 44 | it.result = dp2px(mPrefsMap.getInt("home_icon_bottom_margin", 110).toFloat()) 45 | } 46 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod( 47 | "calcHotSeatsMarginBottom", Context::class.java, Boolean::class.java, Boolean::class.java 48 | ) { 49 | it.result = dp2px(mPrefsMap.getInt("home_dock_icon_bottom_margin", -8).toFloat()) 50 | } 51 | 52 | // Dock 53 | if (atLeastAndroidS() && mPrefsMap.getBoolean("home_dock_blur")) { 54 | hookAllConstructorAfter("com.miui.home.launcher.Launcher") { 55 | var mDockBlur = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDockBlur") 56 | if (mDockBlur != null) return@hookAllConstructorAfter 57 | mDockBlur = BlurFrameLayout(appContext) 58 | XposedHelpers.setAdditionalInstanceField(it.thisObject, "mDockBlur", mDockBlur) 59 | } 60 | launcherClass.hookAfterMethod("onCreate", Bundle::class.java) { 61 | val mSearchBarContainer = it.thisObject.callMethod("getSearchBarContainer") as FrameLayout 62 | val mSearchEdgeLayout = mSearchBarContainer.parent as FrameLayout 63 | val mDockBlur = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDockBlur") as BlurFrameLayout 64 | val lp = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, mDockHeight) 65 | lp.gravity = Gravity.BOTTOM 66 | lp.setMargins(mDockMargin, 0, mDockMargin, mDockBottomMargin) 67 | mDockBlur.blurController.apply { 68 | cornerRadius = CornersRadius.all(mDockCorner.toFloat()) 69 | } 70 | mDockBlur.layoutParams = lp 71 | mSearchEdgeLayout.addView(mDockBlur, 0) 72 | launcherClass.hookAfterMethod("isFolderShowing") { hookParam -> 73 | isFolderShowing = hookParam.result as Boolean 74 | } 75 | launcherClass.hookAfterMethod("showEditPanel", Boolean::class.java) { hookParam -> 76 | isShowEditPanel = hookParam.args[0] as Boolean 77 | if (isShowEditPanel) mDockBlur.visibility = View.GONE 78 | else mDockBlur.visibility = View.VISIBLE 79 | } 80 | launcherClass.hookAfterMethod("openFolder", folderInfo, View::class.java) { 81 | mDockBlur.visibility = View.GONE 82 | } 83 | launcherClass.hookAfterMethod("closeFolder", Boolean::class.java) { 84 | if (!isShowEditPanel) mDockBlur.visibility = View.VISIBLE 85 | } 86 | blurClass.hookAfterMethod( 87 | "fastBlurWhenEnterRecents", launcherClass, launcherStateClass, Boolean::class.java 88 | ) { 89 | mDockBlur.visibility = View.GONE 90 | } 91 | } 92 | launcherClass.hookAfterMethod("onStateSetStart", launcherStateClass) { 93 | val mDockBlur = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDockBlur") as BlurFrameLayout 94 | if ("LauncherState" == it.args[0].javaClass.simpleName && !isFolderShowing && !isShowEditPanel) { 95 | mDockBlur.visibility = View.VISIBLE 96 | } else mDockBlur.visibility = View.GONE 97 | } 98 | } 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/DoubleTapController.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.Context 4 | import android.os.SystemClock 5 | import android.view.MotionEvent 6 | import android.view.ViewConfiguration 7 | 8 | class DoubleTapController internal constructor(mContext: Context) { 9 | 10 | private val maxDuration: Long = 500 11 | private var mActionDownRawX: Float = 0f 12 | private var mActionDownRawY: Float = 0f 13 | private var mClickCount: Int = 0 14 | private var mFirstClickRawX: Float = 0f 15 | private var mFirstClickRawY: Float = 0f 16 | private var mLastClickTime: Long = 0 17 | private val mTouchSlop: Int = ViewConfiguration.get(mContext).scaledTouchSlop * 2 18 | 19 | fun isDoubleTapEvent(motionEvent: MotionEvent): Boolean { 20 | val action = motionEvent.actionMasked 21 | return when { 22 | action == MotionEvent.ACTION_DOWN -> { 23 | mActionDownRawX = motionEvent.rawX 24 | mActionDownRawY = motionEvent.rawY 25 | false 26 | } 27 | 28 | action != MotionEvent.ACTION_UP -> false 29 | else -> { 30 | val rawX = motionEvent.rawX 31 | val rawY = motionEvent.rawY 32 | if (kotlin.math.abs(rawX - mActionDownRawX) <= mTouchSlop.toFloat() && kotlin.math.abs( 33 | rawY - mActionDownRawY 34 | ) <= mTouchSlop.toFloat() 35 | ) { 36 | if (SystemClock.elapsedRealtime() - mLastClickTime > maxDuration || rawY - mFirstClickRawY > mTouchSlop.toFloat() || rawX - mFirstClickRawX > mTouchSlop.toFloat()) mClickCount = 37 | 0 38 | mClickCount++ 39 | if (mClickCount == 1) { 40 | mFirstClickRawX = rawX 41 | mFirstClickRawY = rawY 42 | mLastClickTime = SystemClock.elapsedRealtime() 43 | return false 44 | } else if (kotlin.math.abs(rawY - mFirstClickRawY) <= mTouchSlop.toFloat() && kotlin.math.abs( 45 | rawX - mFirstClickRawX 46 | ) <= mTouchSlop.toFloat() && SystemClock.elapsedRealtime() - mLastClickTime <= maxDuration 47 | ) { 48 | mClickCount = 0 49 | return true 50 | } 51 | } 52 | mClickCount = 0 53 | false 54 | } 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/DoubleTapToSleep.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.view.MotionEvent 6 | import com.github.kyuubiran.ezxhelper.utils.findMethod 7 | import com.github.kyuubiran.ezxhelper.utils.getObject 8 | import com.github.kyuubiran.ezxhelper.utils.hookAllConstructorAfter 9 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 10 | import com.github.kyuubiran.ezxhelper.utils.invokeMethodAuto 11 | import com.yuk.miuiHomeR.mPrefsMap 12 | import de.robv.android.xposed.XposedHelpers 13 | 14 | object DoubleTapToSleep : BaseHook() { 15 | override fun init() { 16 | 17 | if (!mPrefsMap.getBoolean("home_double_sleep")) return 18 | hookAllConstructorAfter("com.miui.home.launcher.Workspace") { 19 | var mDoubleTapControllerEx = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx") 20 | if (mDoubleTapControllerEx != null) return@hookAllConstructorAfter 21 | mDoubleTapControllerEx = DoubleTapController((it.args[0] as Context)) 22 | XposedHelpers.setAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx", mDoubleTapControllerEx) 23 | } 24 | findMethod("com.miui.home.launcher.Workspace") { 25 | name == "dispatchTouchEvent" && parameterCount == 1 26 | }.hookBefore { 27 | val mDoubleTapControllerEx = XposedHelpers.getAdditionalInstanceField(it.thisObject, "mDoubleTapControllerEx") as DoubleTapController 28 | if (!mDoubleTapControllerEx.isDoubleTapEvent(it.args[0] as MotionEvent)) return@hookBefore 29 | val mCurrentScreenIndex = it.thisObject.getObject("mCurrentScreenIndex") 30 | val cellLayout = it.thisObject.invokeMethodAuto("getCellLayout", mCurrentScreenIndex) 31 | if (cellLayout != null) if (cellLayout.invokeMethodAuto("lastDownOnOccupiedCell") as Boolean) return@hookBefore 32 | if (it.thisObject.invokeMethodAuto("isInNormalEditingMode") as Boolean) return@hookBefore 33 | val context = it.thisObject.invokeMethodAuto("getContext") as Context 34 | context.sendBroadcast( 35 | Intent("com.miui.app.ExtraStatusBarManager.action_TRIGGER_TOGGLE").putExtra( 36 | "com.miui.app.ExtraStatusBarManager.extra_TOGGLE_ID", 10 37 | ) 38 | ) 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/EnableBlurWhenOpenFolder.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.app.Activity 4 | import android.os.Bundle 5 | import android.view.View 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 8 | import com.yuk.miuiHomeR.utils.ktx.findClass 9 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 10 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 11 | import com.yuk.miuiHomeR.utils.ktx.isAlpha 12 | 13 | object EnableBlurWhenOpenFolder : BaseHook() { 14 | override fun init() { 15 | 16 | if (mPrefsMap.getStringAsInt( 17 | "recent_blur", 0 18 | ) == 4 || !mPrefsMap.getBoolean("home_folder_blur") 19 | ) { 20 | if (isAlpha()) { 21 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUserBlurWhenOpenFolder") { 22 | it.result = false 23 | } 24 | } 25 | } else { 26 | if (mPrefsMap.getBoolean("home_folder_blur")) { 27 | if (isAlpha()) { 28 | "com.miui.home.launcher.common.BlurUtils".hookBeforeMethod("isUserBlurWhenOpenFolder") { 29 | it.result = true 30 | } 31 | } else { 32 | val blurClass = "com.miui.home.launcher.common.BlurUtils".findClass() 33 | val folderInfo = "com.miui.home.launcher.FolderInfo".findClass() 34 | val launcherClass = "com.miui.home.launcher.Launcher".findClass() 35 | val launcherStateClass = "com.miui.home.launcher.LauncherState".findClass() 36 | val cancelShortcutMenuReasonClass = "com.miui.home.launcher.shortcuts.CancelShortcutMenuReason".findClass() 37 | launcherClass.hookAfterMethod("onCreate", Bundle::class.java) { 38 | val activity = it.thisObject as Activity 39 | var isFolderShowing = false 40 | var isShowEditPanel = false 41 | launcherClass.hookAfterMethod("isFolderShowing") { hookParam -> 42 | isFolderShowing = hookParam.result as Boolean 43 | } 44 | launcherClass.hookAfterMethod("showEditPanel", Boolean::class.java) { hookParam -> 45 | isShowEditPanel = hookParam.args[0] as Boolean 46 | } 47 | launcherClass.hookAfterMethod("openFolder", folderInfo, View::class.java) { 48 | blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true) 49 | } 50 | launcherClass.hookAfterMethod("closeFolder", Boolean::class.java) { 51 | if (isShowEditPanel) blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 52 | else blurClass.callStaticMethod("fastBlur", 0.0f, activity.window, true, 300L) 53 | } 54 | launcherClass.hookAfterMethod("cancelShortcutMenu", Int::class.java, cancelShortcutMenuReasonClass) { 55 | if (isFolderShowing) blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 56 | } 57 | blurClass.hookAfterMethod( 58 | "fastBlurWhenStartOpenOrCloseApp", Boolean::class.java, launcherClass 59 | ) { hookParam -> 60 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 61 | else if (isShowEditPanel) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 62 | } 63 | blurClass.hookAfterMethod( 64 | "fastBlurWhenFinishOpenOrCloseApp", launcherClass 65 | ) { hookParam -> 66 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 67 | else if (isShowEditPanel) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 68 | } 69 | blurClass.hookAfterMethod( 70 | "fastBlurWhenExitRecents", launcherClass, launcherStateClass, Boolean::class.java 71 | ) { hookParam -> 72 | if (isFolderShowing) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 73 | else if (isShowEditPanel) hookParam.result = blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 0L) 74 | } 75 | launcherClass.hookAfterMethod("onGesturePerformAppToHome") { 76 | if (isFolderShowing) blurClass.callStaticMethod("fastBlur", 1.0f, activity.window, true, 300L) 77 | } 78 | } 79 | } 80 | } 81 | } 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/FoldDeviceDock.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.Context 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookMethod 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 8 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 9 | import de.robv.android.xposed.XC_MethodHook 10 | 11 | object FoldDeviceDock : BaseHook() { 12 | override fun init() { 13 | 14 | if (!mPrefsMap.getBoolean("home_fold_dock")) return 15 | var hook1: XC_MethodHook.Unhook? = null 16 | var hook2: XC_MethodHook.Unhook? = null 17 | var hook3: XC_MethodHook.Unhook? = null 18 | findMethod("com.miui.home.launcher.hotseats.HotSeats") { 19 | name == "initContent" 20 | }.hookMethod { 21 | before { 22 | hook1 = "com.miui.home.launcher.DeviceConfig".hookBeforeMethod( 23 | "isFoldDevice" 24 | ) { hookParam -> 25 | hookParam.result = true 26 | } 27 | } 28 | after { 29 | hook1?.unhook() 30 | } 31 | } 32 | 33 | try { 34 | findMethod("com.miui.home.launcher.hotseats.HotSeats") { 35 | name == "updateContent" 36 | } 37 | } catch (e: Exception) { 38 | findMethod("com.miui.home.launcher.hotseats.HotSeats") { 39 | name == "updateContentView" 40 | } 41 | }.hookMethod { 42 | before { 43 | hook2 = "com.miui.home.launcher.Application".hookBeforeMethod( 44 | "isInFoldLargeScreen" 45 | ) { hookParam -> 46 | hookParam.result = true 47 | } 48 | } 49 | after { 50 | hook2?.unhook() 51 | 52 | } 53 | } 54 | 55 | findMethod("com.miui.home.launcher.hotseats.HotSeats") { 56 | name == "isNeedUpdateItemInfo" 57 | }.hookMethod { 58 | before { 59 | hook2 = "com.miui.home.launcher.Application".hookBeforeMethod( 60 | "isInFoldLargeScreen" 61 | ) { hookParam -> 62 | hookParam.result = true 63 | } 64 | } 65 | after { 66 | hook2?.unhook() 67 | } 68 | } 69 | 70 | findMethod("com.miui.home.launcher.hotseats.HotSeatsListRecentsAppProvider\$1") { 71 | name == "handleMessage" && parameterCount == 1 72 | }.hookMethod { 73 | before { 74 | hook3 = "com.miui.home.launcher.Application".hookBeforeMethod("isInFoldLargeScreen") { hookParam -> hookParam.result = true } 75 | } 76 | after { hook3?.unhook() } 77 | } 78 | 79 | "com.miui.home.launcher.DeviceConfig".hookAfterMethod("getHotseatMaxCount") { 80 | it.result = mPrefsMap.getInt("home_fold_dock_hotseat", 3) 81 | } 82 | 83 | "com.miui.home.launcher.hotseats.HotSeatsListRecentsAppProvider".hookBeforeMethod("getLimitCount") { 84 | it.result = mPrefsMap.getInt("home_fold_dock_run", 2) 85 | } 86 | 87 | "com.miui.home.launcher.allapps.LauncherMode".hookBeforeMethod("isHomeSupportSearchBar", Context::class.java) { 88 | it.result = false 89 | } 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/FolderAnim.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookMethod 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | import com.yuk.miuiHomeR.utils.ktx.findClass 7 | import com.yuk.miuiHomeR.utils.ktx.findClassOrNull 8 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 9 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 10 | import de.robv.android.xposed.XC_MethodHook 11 | 12 | object FolderAnim : BaseHook() { 13 | override fun init() { 14 | 15 | if (!mPrefsMap.getBoolean("home_folder_anim")) return 16 | val value1 = mPrefsMap.getInt("home_folder_anim_1", 90).toFloat() / 100 17 | val value2 = mPrefsMap.getInt("home_folder_anim_2", 30).toFloat() / 100 18 | val value3 = mPrefsMap.getInt("home_folder_anim_3", 99).toFloat() / 100 19 | val value4 = mPrefsMap.getInt("home_folder_anim_4", 24).toFloat() / 100 20 | val mSpringAnimator = "com.miui.home.launcher.animate.SpringAnimator".findClass() 21 | var hook1: XC_MethodHook.Unhook? = null 22 | var hook2: XC_MethodHook.Unhook? = null 23 | for (i in 47..60) { 24 | val launcherClass = "com.miui.home.launcher.Launcher$$i".findClassOrNull() 25 | if (launcherClass != null) { 26 | for (field in launcherClass.declaredFields) { 27 | if (field.name == "val\$folderInfo") { 28 | findMethod(launcherClass) { 29 | name == "run" 30 | }.hookMethod { 31 | before { 32 | hook1 = mSpringAnimator.hookBeforeMethod( 33 | "setDampingResponse", Float::class.javaPrimitiveType, Float::class.javaPrimitiveType 34 | ) { 35 | it.args[0] = value1 36 | it.args[1] = value2 37 | } 38 | } 39 | after { 40 | hook1?.unhook() 41 | } 42 | } 43 | break 44 | } 45 | } 46 | } 47 | } 48 | 49 | "com.miui.home.launcher.Launcher".hookBeforeMethod("closeFolder", Boolean::class.java) { 50 | if (it.args[0] == true) { 51 | hook2 = mSpringAnimator.hookBeforeMethod( 52 | "setDampingResponse", Float::class.javaPrimitiveType, Float::class.javaPrimitiveType 53 | ) { hookParam -> 54 | hookParam.args[0] = value3 55 | hookParam.args[1] = value4 56 | } 57 | } 58 | } 59 | "com.miui.home.launcher.Launcher".hookAfterMethod("closeFolder", Boolean::class.java) { 60 | hook2?.unhook() 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/FolderColumnsCount.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.view.ViewGroup 4 | import android.widget.GridView 5 | import com.github.kyuubiran.ezxhelper.utils.loadClass 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllMethods 8 | import de.robv.android.xposed.XposedHelpers 9 | 10 | object FolderColumnsCount : BaseHook() { 11 | override fun init() { 12 | 13 | val value = mPrefsMap.getInt("home_folder_columns", 3) 14 | if (value == 3) return 15 | loadClass("com.miui.home.launcher.Folder").hookAfterAllMethods( 16 | "bind" 17 | ) { 18 | val columns: Int = value 19 | val mContent = XposedHelpers.getObjectField(it.thisObject, "mContent") as GridView 20 | mContent.numColumns = columns 21 | if (mPrefsMap.getBoolean("home_folder_width") && (columns > 3)) { 22 | mContent.setPadding(0, 0, 0, 0) 23 | val lp = mContent.layoutParams 24 | lp.width = ViewGroup.LayoutParams.MATCH_PARENT 25 | mContent.layoutParams = lp 26 | } 27 | if (columns > 3) { 28 | val mBackgroundView = XposedHelpers.getObjectField(it.thisObject, "mBackgroundView") as ViewGroup 29 | mBackgroundView.setPadding( 30 | mBackgroundView.paddingLeft / 3, mBackgroundView.paddingTop, mBackgroundView.paddingRight / 3, mBackgroundView.paddingBottom 31 | ) 32 | } 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/FolderVerticalPadding.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.widget.GridView 4 | import com.github.kyuubiran.ezxhelper.utils.loadClass 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | import com.yuk.miuiHomeR.utils.ktx.dp2px 7 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllMethods 8 | import de.robv.android.xposed.XposedHelpers 9 | 10 | object FolderVerticalPadding : BaseHook() { 11 | override fun init() { 12 | 13 | val verticalPadding = mPrefsMap.getInt("home_folder_vertical_padding", 0) 14 | if (verticalPadding <= 0) return 15 | loadClass("com.miui.home.launcher.Folder").hookAfterAllMethods( 16 | "bind" 17 | ) { 18 | val mContent = XposedHelpers.getObjectField(it.thisObject, "mContent") as GridView 19 | mContent.verticalSpacing = dp2px(verticalPadding.toFloat()) 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/HapticFeedback.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.yuk.miuiHomeR.mPrefsMap 5 | import com.yuk.miuiHomeR.utils.ktx.callMethod 6 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 7 | import com.yuk.miuiHomeR.utils.ktx.replaceMethod 8 | 9 | object HapticFeedback : BaseHook() { 10 | override fun init() { 11 | 12 | if (!mPrefsMap.getBoolean("haptic_feedback")) return 13 | val value = mPrefsMap.getInt("haptic_Back_HandUp", 2) 14 | val value1 = mPrefsMap.getInt("haptic_Back_ReadyBack", 2) 15 | findMethod("com.miui.home.launcher.common.HapticFeedbackCompatLinear") { 16 | name == "lambda\$performGestureBackHandUp\$8" && parameterCount == 1 17 | }.replaceMethod { 18 | it.args[0].getObjectField("mHapticHelper")?.callMethod("performExtHapticFeedback", value) 19 | } 20 | 21 | findMethod("com.miui.home.launcher.common.HapticFeedbackCompatLinear") { 22 | name == "lambda\$performGestureReadyBack\$7" && parameterCount == 1 23 | }.replaceMethod { 24 | it.args[0].getObjectField("mHapticHelper")?.callMethod("performExtHapticFeedback", value1) 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/HideSeekPoint.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.view.View 4 | import android.view.ViewGroup 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | import com.yuk.miuiHomeR.utils.ktx.callMethod 7 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 8 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 9 | 10 | object HideSeekPoint : BaseHook() { 11 | override fun init() { 12 | 13 | if (!mPrefsMap.getBoolean("home_hide_seek_point")) return 14 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 15 | "updateSeekPoints", Int::class.javaPrimitiveType 16 | ) { 17 | showSeekBar(it.thisObject as View) 18 | } 19 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 20 | "addView", View::class.java, Int::class.javaPrimitiveType, ViewGroup.LayoutParams::class.java 21 | ) { 22 | showSeekBar(it.thisObject as View) 23 | } 24 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 25 | "removeScreen", Int::class.javaPrimitiveType 26 | ) { 27 | showSeekBar(it.thisObject as View) 28 | } 29 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 30 | "removeScreensInLayout", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType 31 | ) { 32 | showSeekBar(it.thisObject as View) 33 | } 34 | } 35 | 36 | private fun showSeekBar(view: View) { 37 | if ("Workspace" != view.javaClass.simpleName) return 38 | val mScreenSeekBar = view.getObjectField("mScreenSeekBar") as View 39 | val isInEditingMode = view.callMethod("isInNormalEditingMode") as Boolean 40 | if (!isInEditingMode) { 41 | mScreenSeekBar.animate().cancel() 42 | mScreenSeekBar.visibility = View.GONE 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/HideStatusBarWhenEnterRecent.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object HideStatusBarWhenEnterRecent : BaseHook() { 8 | override fun init() { 9 | 10 | if (mPrefsMap.getBoolean("home_hide_status")) { 11 | findMethod("com.miui.home.launcher.common.DeviceLevelUtils") { 12 | name == "isHideStatusBarWhenEnterRecents" 13 | }.hookReturnConstant(true) 14 | findMethod("com.miui.home.launcher.DeviceConfig") { 15 | name == "keepStatusBarShowingForBetterPerformance" 16 | }.hookReturnConstant(false) 17 | } else { 18 | findMethod("com.miui.home.launcher.common.DeviceLevelUtils") { 19 | name == "isHideStatusBarWhenEnterRecents" 20 | }.hookReturnConstant(false) 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/HideWidgetTitles.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.view.View 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookAfter 6 | import com.github.kyuubiran.ezxhelper.utils.invokeMethodAuto 7 | import com.github.kyuubiran.ezxhelper.utils.loadClass 8 | import com.yuk.miuiHomeR.mPrefsMap 9 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 10 | import java.util.function.Predicate 11 | 12 | object HideWidgetTitles : BaseHook() { 13 | override fun init() { 14 | 15 | if (!mPrefsMap.getBoolean("home_widget_hide")) return 16 | val maMlWidgetInfo = loadClass("com.miui.home.launcher.maml.MaMlWidgetInfo") 17 | findMethod("com.miui.home.launcher.LauncherAppWidgetHost") { 18 | name == "createLauncherWidgetView" && parameterCount == 4 19 | }.hookAfter { 20 | val view = it.result as Any 21 | view.invokeMethodAuto("getTitleView")?.invokeMethodAuto("setVisibility", View.GONE) 22 | } 23 | "com.miui.home.launcher.Launcher".hookAfterMethod( 24 | "addMaMl", maMlWidgetInfo, Boolean::class.java, Predicate::class.java 25 | ) { 26 | val view = it.result as Any 27 | view.invokeMethodAuto("getTitleView")?.invokeMethodAuto("setVisibility", View.GONE) 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/HomeSettings.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.ComponentName 4 | import android.content.Intent 5 | import android.view.View 6 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext 7 | import com.github.kyuubiran.ezxhelper.init.InitFields.moduleRes 8 | import com.yuk.miuiHomeR.R 9 | import com.yuk.miuiHomeR.utils.ktx.callMethod 10 | import com.yuk.miuiHomeR.utils.ktx.findClass 11 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 12 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllMethods 13 | import com.yuk.miuiHomeR.utils.ktx.setObjectField 14 | import de.robv.android.xposed.XposedHelpers 15 | 16 | object HomeSettings : BaseHook() { 17 | override fun init() { 18 | 19 | "com.miui.home.settings.MiuiHomeSettings".findClass().hookAfterAllMethods("onCreatePreferences") { 20 | val mLayoutResId = (it.thisObject.getObjectField("mAllAppsSetting"))?.getObjectField("mLayoutResId") 21 | val mWidgetLayoutResId = (it.thisObject.getObjectField("mAllAppsSetting"))?.getObjectField("mWidgetLayoutResId") 22 | val pref = XposedHelpers.newInstance("com.miui.home.settings.preference.ValuePreference".findClass(), appContext).apply { 23 | setObjectField("mTitle", "MiuiHomeR") 24 | setObjectField("mOrder", 0) 25 | setObjectField("mVisible", true) 26 | setObjectField("mLayoutResId", mLayoutResId) 27 | setObjectField("mWidgetLayoutResId", mWidgetLayoutResId) 28 | setObjectField("mFragment", "MiuiHomeR") 29 | callMethod("setValue", moduleRes.getString(R.string.module_settings)) 30 | setObjectField("mClickListener", object : View.OnClickListener { 31 | override fun onClick(v: View) { 32 | val intent = Intent() 33 | intent.component = ComponentName("com.yuk.miuiHomeR", "com.yuk.miuiHomeR.ui.MainActivity") 34 | intent.putExtra("homeAsUpEnabled", true) 35 | v.context.startActivity(intent) 36 | } 37 | }) 38 | callMethod("setIntent", Intent()) 39 | } 40 | it.thisObject.callMethod("getPreferenceScreen")?.callMethod("addPreference", pref) 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/IconTitleColor.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import com.github.kyuubiran.ezxhelper.utils.Log 9 | import com.yuk.miuiHomeR.mPrefsMap 10 | import com.yuk.miuiHomeR.utils.ktx.callMethod 11 | import com.yuk.miuiHomeR.utils.ktx.findClass 12 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 13 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 14 | 15 | object IconTitleColor : BaseHook() { 16 | @SuppressLint("DiscouragedApi") 17 | override fun init() { 18 | 19 | val value = mPrefsMap.getInt("icon_title_font_color", -1) 20 | val launcherClass = "com.miui.home.launcher.Launcher".findClass() 21 | val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass() 22 | if (value == -1) return 23 | try { 24 | "com.miui.home.launcher.ItemIcon".hookAfterMethod( 25 | "onFinishInflate" 26 | ) { 27 | val mTitle = it.thisObject.getObjectField("mTitle") as TextView 28 | mTitle.setTextColor(value) 29 | } 30 | "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod( 31 | "onFinishInflate" 32 | ) { 33 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 34 | mTitle.setTextColor(value) 35 | } 36 | "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod( 37 | "onFinishInflate" 38 | ) { 39 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 40 | mTitle.setTextColor(value) 41 | } 42 | "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod( 43 | "onFinishInflate" 44 | ) { 45 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 46 | mTitle.setTextColor(value) 47 | } 48 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 49 | "fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass 50 | ) { 51 | val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View 52 | val mTitle = buddyIconView.getObjectField("mTitle") as TextView 53 | mTitle.setTextColor(value) 54 | } 55 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 56 | "createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java 57 | ) { 58 | val buddyIcon = it.result as View 59 | val mTitle = buddyIcon.getObjectField("mTitle") as TextView 60 | mTitle.setTextColor(value) 61 | } 62 | "com.miui.home.launcher.common.Utilities".hookAfterMethod( 63 | "adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType 64 | ) { 65 | val mTitle = it.args[1] as TextView 66 | if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", "com.miui.home")) { 67 | mTitle.setTextColor(value) 68 | } 69 | } 70 | } catch (e: Throwable) { 71 | Log.ex(e) 72 | } 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/IconTitleScrolling.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.text.TextUtils 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.TextView 9 | import com.github.kyuubiran.ezxhelper.utils.Log 10 | import com.yuk.miuiHomeR.mPrefsMap 11 | import com.yuk.miuiHomeR.utils.ktx.callMethod 12 | import com.yuk.miuiHomeR.utils.ktx.findClass 13 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 14 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 15 | 16 | object IconTitleScrolling : BaseHook() { 17 | @SuppressLint("DiscouragedApi") 18 | override fun init() { 19 | 20 | if (!mPrefsMap.getBoolean("icon_title_font_scrolling")) return 21 | val launcherClass = "com.miui.home.launcher.Launcher".findClass() 22 | val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass() 23 | try { 24 | "com.miui.home.launcher.ItemIcon".hookAfterMethod( 25 | "onFinishInflate" 26 | ) { 27 | val mTitle = it.thisObject.getObjectField("mTitle") as TextView 28 | mTitleScrolling(mTitle) 29 | } 30 | "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod( 31 | "onFinishInflate" 32 | ) { 33 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 34 | mTitleScrolling(mTitle) 35 | } 36 | "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod( 37 | "onFinishInflate" 38 | ) { 39 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 40 | mTitleScrolling(mTitle) 41 | } 42 | "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod( 43 | "onFinishInflate" 44 | ) { 45 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 46 | mTitleScrolling(mTitle) 47 | } 48 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 49 | "fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass 50 | ) { 51 | val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View 52 | val mTitle = buddyIconView.getObjectField("mTitle") as TextView 53 | mTitleScrolling(mTitle) 54 | } 55 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 56 | "createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java 57 | ) { 58 | val buddyIcon = it.result as View 59 | val mTitle = buddyIcon.getObjectField("mTitle") as TextView 60 | mTitleScrolling(mTitle) 61 | } 62 | "com.miui.home.launcher.common.Utilities".hookAfterMethod( 63 | "adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType 64 | ) { 65 | val mTitle = it.args[1] as TextView 66 | if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", "com.miui.home")) { 67 | mTitleScrolling(mTitle) 68 | } 69 | } 70 | } catch (e: Throwable) { 71 | Log.ex(e) 72 | } 73 | 74 | } 75 | 76 | private fun mTitleScrolling(mTitle: TextView) { 77 | mTitle.ellipsize = TextUtils.TruncateAt.MARQUEE 78 | mTitle.isHorizontalFadingEdgeEnabled = true 79 | mTitle.setSingleLine() 80 | mTitle.marqueeRepeatLimit = -1 81 | mTitle.isSelected = true 82 | mTitle.setHorizontallyScrolling(true) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/IconTitleSize.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.util.TypedValue 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.TextView 9 | import com.github.kyuubiran.ezxhelper.utils.Log 10 | import com.yuk.miuiHomeR.mPrefsMap 11 | import com.yuk.miuiHomeR.utils.ktx.callMethod 12 | import com.yuk.miuiHomeR.utils.ktx.findClass 13 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 14 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 15 | 16 | object IconTitleSize : BaseHook() { 17 | @SuppressLint("DiscouragedApi") 18 | override fun init() { 19 | 20 | val value = mPrefsMap.getInt("icon_title_font_size", -1).toFloat() 21 | val launcherClass = "com.miui.home.launcher.Launcher".findClass() 22 | val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass() 23 | if (value == -1f) return 24 | try { 25 | "com.miui.home.launcher.ItemIcon".hookAfterMethod( 26 | "onFinishInflate" 27 | ) { 28 | val mTitle = it.thisObject.getObjectField("mTitle") as TextView 29 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 30 | } 31 | "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod( 32 | "onFinishInflate" 33 | ) { 34 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 35 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 36 | } 37 | "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod( 38 | "onFinishInflate" 39 | ) { 40 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 41 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 42 | } 43 | "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod( 44 | "onFinishInflate" 45 | ) { 46 | val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView 47 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 48 | } 49 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 50 | "fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass 51 | ) { 52 | val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View 53 | val mTitle = buddyIconView.getObjectField("mTitle") as TextView 54 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 55 | } 56 | "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( 57 | "createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java 58 | ) { 59 | val buddyIcon = it.result as View 60 | val mTitle = buddyIcon.getObjectField("mTitle") as TextView 61 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 62 | } 63 | "com.miui.home.launcher.common.Utilities".hookAfterMethod( 64 | "adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType 65 | ) { 66 | val mTitle = it.args[1] as TextView 67 | if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", "com.miui.home")) { 68 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, value) 69 | } 70 | } 71 | } catch (e: Throwable) { 72 | Log.ex(e) 73 | } 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/InfiniteScroll.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.yuk.miuiHomeR.mPrefsMap 4 | import com.yuk.miuiHomeR.utils.ktx.callMethod 5 | import com.yuk.miuiHomeR.utils.ktx.getIntField 6 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 7 | 8 | object InfiniteScroll : BaseHook() { 9 | override fun init() { 10 | 11 | if (!mPrefsMap.getBoolean("home_infinite_scroll")) return 12 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 13 | "getSnapToScreenIndex", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType 14 | ) { 15 | if (it.args[0] !== it.result) return@hookAfterMethod 16 | val screenCount = it.thisObject.callMethod("getScreenCount") as Int 17 | if (it.args[2] as Int == -1 && it.args[0] as Int == 0) it.result = screenCount 18 | else if (it.args[2] as Int == 1 && it.args[0] as Int == screenCount - 1) it.result = 0 19 | } 20 | "com.miui.home.launcher.ScreenView".hookAfterMethod( 21 | "getSnapUnitIndex", Int::class.javaPrimitiveType 22 | ) { 23 | val mCurrentScreenIndex = it.thisObject.getIntField("mCurrentScreenIndex") 24 | if (mCurrentScreenIndex != it.result as Int) return@hookAfterMethod 25 | val screenCount = it.thisObject.callMethod("getScreenCount") as Int 26 | if (it.result as Int == 0) it.result = screenCount 27 | else if (it.result as Int == screenCount - 1) it.result = 0 28 | } 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/OverlapMode.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object OverlapMode : BaseHook() { 8 | override fun init() { 9 | 10 | if (!mPrefsMap.getBoolean("home_overlap_mode")) return 11 | findMethod("com.miui.home.launcher.overlay.assistant.AssistantDeviceAdapter") { 12 | name == "inOverlapMode" 13 | }.hookReturnConstant(true) 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/Recent.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.util.TypedValue 4 | import android.view.View 5 | import android.widget.ImageView 6 | import android.widget.TextView 7 | import com.yuk.miuiHomeR.mPrefsMap 8 | import com.yuk.miuiHomeR.utils.ktx.findClass 9 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 10 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllConstructors 11 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 12 | import com.yuk.miuiHomeR.utils.ktx.setIntField 13 | 14 | object Recent : BaseHook() { 15 | override fun init() { 16 | 17 | val recentsContainerClass = "com.miui.home.recents.views.RecentsContainer".findClass() 18 | if (mPrefsMap.getBoolean("home_hide_small_window")) { 19 | recentsContainerClass.hookAfterMethod( 20 | "onFinishInflate" 21 | ) { 22 | val mTitle = it.thisObject.getObjectField("mTxtSmallWindow") as TextView 23 | mTitle.visibility = View.GONE 24 | } 25 | } 26 | 27 | if (mPrefsMap.getBoolean("home_hide_clean_up")) { 28 | recentsContainerClass.hookAfterMethod( 29 | "onFinishInflate" 30 | ) { 31 | val mView = it.thisObject.getObjectField("mClearAnimView") as View 32 | mView.visibility = View.GONE 33 | } 34 | } 35 | 36 | val appCardBgColor = mPrefsMap.getInt("recents_card_bg_color", -1) 37 | if (appCardBgColor != -1) { 38 | "com.miui.home.recents.views.TaskViewThumbnail".findClass().hookAfterAllConstructors { 39 | it.thisObject.setIntField("mBgColorForSmallWindow", appCardBgColor) 40 | } 41 | } 42 | 43 | val recentTextSize = mPrefsMap.getInt("recents_text_size", -1) 44 | if (recentTextSize != -1) { 45 | val taskViewHeaderClass = "com.miui.home.recents.views.TaskViewHeader".findClass() 46 | taskViewHeaderClass.hookAfterMethod( 47 | "onFinishInflate" 48 | ) { 49 | val mTitle = it.thisObject.getObjectField("mTitleView") as TextView 50 | mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, recentTextSize.toFloat()) 51 | if (recentTextSize == 0) mTitle.visibility = View.GONE 52 | } 53 | } 54 | 55 | val recentTextColor = mPrefsMap.getInt("recents_text_color", -1) 56 | if (recentTextSize != -1) { 57 | val taskViewHeaderClass = "com.miui.home.recents.views.TaskViewHeader".findClass() 58 | taskViewHeaderClass.hookAfterMethod( 59 | "onFinishInflate" 60 | ) { 61 | val mTitle = it.thisObject.getObjectField("mTitleView") as TextView 62 | mTitle.setTextColor(recentTextColor) 63 | } 64 | } 65 | 66 | val emptyViewText = mPrefsMap.getString("recent_text", "") 67 | if (emptyViewText != "") { 68 | "com.miui.home.recents.views.RecentsView".hookAfterMethod( 69 | "showEmptyView", Int::class.javaPrimitiveType 70 | ) { 71 | (it.thisObject.getObjectField("mEmptyView") as TextView).apply { 72 | this.text = emptyViewText 73 | } 74 | } 75 | } 76 | 77 | if (mPrefsMap.getBoolean("recents_icon")) { 78 | "com.miui.home.recents.views.TaskViewHeader".hookAfterMethod( 79 | "onFinishInflate" 80 | ) { 81 | val mImage = it.thisObject.getObjectField("mIconView") as ImageView 82 | mImage.visibility = View.GONE 83 | } 84 | } 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/RemoveCardAnim.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.animation.ObjectAnimator 4 | import android.view.MotionEvent 5 | import android.view.View 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.callMethod 8 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 9 | import com.yuk.miuiHomeR.utils.ktx.findClass 10 | import com.yuk.miuiHomeR.utils.ktx.getObjectField 11 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 12 | import com.yuk.miuiHomeR.utils.ktx.replaceMethod 13 | import com.yuk.miuiHomeR.utils.ktx.setObjectField 14 | 15 | object RemoveCardAnim : BaseHook() { 16 | override fun init() { 17 | 18 | if (!mPrefsMap.getBoolean("recents_card_remove_anim")) return 19 | "com.miui.home.recents.views.SwipeHelperForRecents".hookAfterMethod("onTouchEvent", MotionEvent::class.java) { 20 | if (it.thisObject.getObjectField("mCurrView") != null) { 21 | val taskView2 = it.thisObject.getObjectField("mCurrView") as View 22 | taskView2.alpha = 1f 23 | taskView2.scaleX = 1f 24 | taskView2.scaleY = 1f 25 | } 26 | } 27 | "com.miui.home.recents.TaskStackViewLayoutStyleHorizontal".replaceMethod( 28 | "createScaleDismissAnimation", View::class.java, Float::class.java 29 | ) { 30 | val view = it.args[0] as View 31 | val getScreenHeight = "com.miui.home.launcher.DeviceConfig".findClass().callStaticMethod("getScreenHeight") as Int 32 | val ofFloat = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, view.translationY, -getScreenHeight * 1.1484375f) 33 | ofFloat.duration = 200 34 | return@replaceMethod ofFloat 35 | } 36 | 37 | "com.miui.home.recents.views.VerticalSwipe".hookAfterMethod("calculate", Float::class.java) { 38 | val f = it.args[0] as Float 39 | val asScreenHeightWhenDismiss = 40 | "com.miui.home.recents.views.VerticalSwipe".findClass().callStaticMethod("getAsScreenHeightWhenDismiss") as Int 41 | val f2 = f / asScreenHeightWhenDismiss 42 | val mTaskViewHeight = it.thisObject.getObjectField("mTaskViewHeight") as Float 43 | val mCurScale = it.thisObject.getObjectField("mCurScale") as Float 44 | val f3: Float = mTaskViewHeight * mCurScale 45 | val i = if (f2 > 0.0f) 1 else if (f2 == 0.0f) 0 else -1 46 | val afterFrictionValue: Float = it.thisObject.callMethod("afterFrictionValue", f, asScreenHeightWhenDismiss) as Float 47 | if (i < 0) it.thisObject.setObjectField("mCurTransY", (mTaskViewHeight / 2.0f + afterFrictionValue * 2) - (f3 / 2.0f)) 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/ResourcesHook.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.content.res.Resources 4 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext 5 | import com.github.kyuubiran.ezxhelper.utils.Log 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ResourcesHookData 8 | import com.yuk.miuiHomeR.utils.ResourcesHookMap 9 | import com.yuk.miuiHomeR.utils.ktx.dp2px 10 | import com.yuk.miuiHomeR.utils.ktx.findClass 11 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeAllMethods 12 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 13 | import de.robv.android.xposed.XC_MethodHook 14 | 15 | object ResourcesHook : BaseHook() { 16 | private val hookMap = ResourcesHookMap() 17 | private fun hook(param: XC_MethodHook.MethodHookParam) { 18 | try { 19 | val resName = appContext.resources.getResourceEntryName(param.args[0] as Int) 20 | val resType = appContext.resources.getResourceTypeName(param.args[0] as Int) 21 | if (hookMap.isKeyExist(resName)) if (hookMap[resName]?.type == resType) { 22 | param.result = hookMap[resName]?.afterValue 23 | } 24 | } catch (ignore: Exception) { 25 | } 26 | } 27 | 28 | override fun init() { 29 | 30 | Resources::class.java.hookBeforeMethod("getBoolean", Int::class.javaPrimitiveType) { hook(it) } 31 | Resources::class.java.hookBeforeMethod("getDimension", Int::class.javaPrimitiveType) { hook(it) } 32 | Resources::class.java.hookBeforeMethod("getDimensionPixelOffset", Int::class.javaPrimitiveType) { hook(it) } 33 | Resources::class.java.hookBeforeMethod("getDimensionPixelSize", Int::class.javaPrimitiveType) { hook(it) } 34 | Resources::class.java.hookBeforeMethod("getInteger", Int::class.javaPrimitiveType) { hook(it) } 35 | Resources::class.java.hookBeforeMethod("getText", Int::class.javaPrimitiveType) { hook(it) } 36 | 37 | val value = mPrefsMap.getInt("task_view_corners", -1).toFloat() 38 | val value1 = mPrefsMap.getInt("task_view_header_height", -1).toFloat() 39 | if (mPrefsMap.getBoolean("home_unlock_grids")) { 40 | val deviceClass = "com.miui.home.launcher.compat.LauncherCellCountCompatDevice".findClass() 41 | deviceClass.hookBeforeAllMethods("shouldUseDeviceValue") { it.result = false } 42 | hookMap["config_cell_count_x"] = ResourcesHookData("integer", 3) 43 | hookMap["config_cell_count_y"] = ResourcesHookData("integer", 4) 44 | hookMap["config_cell_count_x_min"] = ResourcesHookData("integer", 3) 45 | hookMap["config_cell_count_y_min"] = ResourcesHookData("integer", 4) 46 | hookMap["config_cell_count_x_max"] = ResourcesHookData("integer", 16) 47 | hookMap["config_cell_count_y_max"] = ResourcesHookData("integer", 18) 48 | try { 49 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isThemeCoverCellConfig") { 50 | it.result = true 51 | } 52 | } catch (e: Throwable) { 53 | Log.ex(e) 54 | } 55 | } 56 | if (value != -1f && value != 20f) { 57 | hookMap["recents_task_view_rounded_corners_radius_min"] = ResourcesHookData("dimen", dp2px(value)) 58 | hookMap["recents_task_view_rounded_corners_radius_max"] = ResourcesHookData("dimen", dp2px(value)) 59 | } 60 | if (value1 != -1f && value != 40f) hookMap["recents_task_view_header_height"] = ResourcesHookData("dimen", dp2px(value1)) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/SetDeviceLevel.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.Log 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookReturnConstant 6 | import com.yuk.miuiHomeR.utils.ktx.checkVersionCode 7 | import com.yuk.miuiHomeR.utils.ktx.findClass 8 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 9 | import com.yuk.miuiHomeR.utils.ktx.replaceMethod 10 | 11 | object SetDeviceLevel : BaseHook() { 12 | override fun init() { 13 | 14 | try { 15 | findMethod("com.miui.home.launcher.common.CpuLevelUtils") { 16 | name == "getQualcommCpuLevel" && parameterCount == 1 17 | } 18 | } catch (e: Exception) { 19 | findMethod("miuix.animation.utils.DeviceUtils") { 20 | name == "getQualcommCpuLevel" && parameterCount == 1 21 | } 22 | }.hookReturnConstant(2) 23 | try { 24 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("getDeviceLevel") { 25 | it.result = 2 26 | } 27 | } catch (e: Throwable) { 28 | Log.ex(e) 29 | } 30 | try { 31 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isSupportCompleteAnimation") { 32 | it.result = true 33 | } 34 | } catch (e: Throwable) { 35 | Log.ex(e) 36 | } 37 | try { 38 | "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isLowLevelOrLiteDevice") { 39 | it.result = false 40 | } 41 | } catch (e: Throwable) { 42 | Log.ex(e) 43 | } 44 | try { 45 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isMiuiLiteVersion") { 46 | it.result = false 47 | } 48 | } catch (e: Throwable) { 49 | Log.ex(e) 50 | } 51 | try { 52 | "com.miui.home.launcher.util.noword.NoWordSettingHelperKt".hookBeforeMethod("isNoWordAvailable") { 53 | it.result = true 54 | } 55 | } catch (e: Throwable) { 56 | Log.ex(e) 57 | } 58 | try { 59 | "android.os.SystemProperties".hookBeforeMethod( 60 | "getBoolean", String::class.java, Boolean::class.java 61 | ) { 62 | if (it.args[0] == "ro.config.low_ram.threshold_gb") it.result = false 63 | } 64 | } catch (e: Throwable) { 65 | Log.ex(e) 66 | } 67 | try { 68 | "android.os.SystemProperties".hookBeforeMethod( 69 | "getBoolean", String::class.java, Boolean::class.java 70 | ) { 71 | if (it.args[0] == "ro.miui.backdrop_sampling_enabled") it.result = true 72 | } 73 | } catch (e: Throwable) { 74 | Log.ex(e) 75 | } 76 | try { 77 | "com.miui.home.launcher.common.Utilities".hookBeforeMethod("canLockTaskView") { 78 | it.result = true 79 | } 80 | } catch (e: Throwable) { 81 | Log.ex(e) 82 | } 83 | try { 84 | "com.miui.home.launcher.MIUIWidgetUtil".hookBeforeMethod("isMIUIWidgetSupport") { 85 | it.result = true 86 | } 87 | } catch (e: Throwable) { 88 | Log.ex(e) 89 | } 90 | try { 91 | if (checkVersionCode() <= 426004312L) "com.miui.home.launcher.MiuiHomeLog".hookBeforeMethod( 92 | "setDebugLogState", Boolean::class.java 93 | ) { 94 | it.result = false 95 | } 96 | } catch (e: Throwable) { 97 | Log.ex(e) 98 | } 99 | try { 100 | "com.miui.home.launcher.MiuiHomeLog".findClass().replaceMethod( 101 | "log", String::class.java, String::class.java 102 | ) { 103 | return@replaceMethod null 104 | } 105 | } catch (e: Throwable) { 106 | Log.ex(e) 107 | } 108 | try { 109 | "com.xiaomi.onetrack.OneTrack".hookBeforeMethod("isDisable") { 110 | it.result = true 111 | } 112 | } catch (e: Throwable) { 113 | Log.ex(e) 114 | } 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/ShortcutItemCount.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | 4 | import com.github.kyuubiran.ezxhelper.utils.findMethod 5 | import com.github.kyuubiran.ezxhelper.utils.hookAfter 6 | import com.yuk.miuiHomeR.mPrefsMap 7 | import com.yuk.miuiHomeR.utils.ktx.callMethod 8 | 9 | object ShortcutItemCount : BaseHook() { 10 | override fun init() { 11 | 12 | if (!mPrefsMap.getBoolean("shortcut_remove_restrictions")) return 13 | findMethod("com.miui.home.launcher.shortcuts.AppShortcutMenu") { name == "getMaxCountInCurrentOrientation" }.hookAfter { 14 | it.result = 20 15 | } 16 | findMethod("com.miui.home.launcher.shortcuts.AppShortcutMenu") { name == "getMaxShortcutItemCount" }.hookAfter { 17 | it.result = 20 18 | } 19 | findMethod("com.miui.home.launcher.shortcuts.AppShortcutMenu") { name == "getMaxVisualHeight" }.hookAfter { 20 | it.result = it.thisObject.callMethod("getItemHeight") 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/ShortcutSmallWindow.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.ComponentName 5 | import android.content.Intent 6 | import android.os.Bundle 7 | import android.view.View 8 | import com.github.kyuubiran.ezxhelper.init.InitFields.moduleRes 9 | import com.yuk.miuiHomeR.R 10 | import com.yuk.miuiHomeR.mPrefsMap 11 | import com.yuk.miuiHomeR.utils.ktx.callMethod 12 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 13 | import com.yuk.miuiHomeR.utils.ktx.findClass 14 | import com.yuk.miuiHomeR.utils.ktx.getStaticObjectField 15 | import com.yuk.miuiHomeR.utils.ktx.hookAfterAllMethods 16 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 17 | import com.yuk.miuiHomeR.utils.ktx.isDarkMode 18 | import com.yuk.miuiHomeR.utils.ktx.setStaticObjectField 19 | import de.robv.android.xposed.XposedBridge 20 | import de.robv.android.xposed.XposedHelpers 21 | 22 | @SuppressLint("StaticFieldLeak", "DiscouragedApi") 23 | object ShortcutSmallWindow : BaseHook() { 24 | @SuppressLint("UseCompatLoadingForDrawables") 25 | override fun init() { 26 | 27 | if (!mPrefsMap.getBoolean("shortcut_small_window")) return 28 | val mViewDarkModeHelper = ("com.miui.home.launcher.util.ViewDarkModeHelper").findClass() 29 | val mSystemShortcutMenu = ("com.miui.home.launcher.shortcuts.SystemShortcutMenu").findClass() 30 | val mSystemShortcutMenuItem = ("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem").findClass() 31 | val mAppShortcutMenu = ("com.miui.home.launcher.shortcuts.AppShortcutMenu").findClass() 32 | val mShortcutMenuItem = ("com.miui.home.launcher.shortcuts.ShortcutMenuItem").findClass() 33 | val mAppDetailsShortcutMenuItem = ("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem\$AppDetailsShortcutMenuItem").findClass() 34 | val mActivityUtilsCompat = ("com.miui.launcher.utils.ActivityUtilsCompat").findClass() 35 | mViewDarkModeHelper.hookAfterAllMethods("onConfigurationChanged") { 36 | mSystemShortcutMenuItem.callStaticMethod("createAllSystemShortcutMenuItems") 37 | } 38 | mShortcutMenuItem.hookAfterAllMethods("getShortTitle") { 39 | if (it.result == "应用信息") { 40 | it.result = "信息" 41 | } 42 | } 43 | mAppDetailsShortcutMenuItem.hookBeforeMethod("lambda\$getOnClickListener$0", mAppDetailsShortcutMenuItem, View::class.java) { 44 | val obj = it.args[0] 45 | val view: View = it.args[1] as View 46 | val mShortTitle = obj.callMethod("getShortTitle") as CharSequence 47 | if (mShortTitle == moduleRes.getString(R.string.small_window)) { 48 | it.result = null 49 | val intent = Intent() 50 | val mComponentName = obj.callMethod("getComponentName") as ComponentName 51 | intent.action = "android.intent.action.MAIN" 52 | intent.addCategory("android.intent.category.DEFAULT") 53 | intent.component = mComponentName 54 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 55 | val callStaticMethod = mActivityUtilsCompat.callStaticMethod("makeFreeformActivityOptions", view.context, mComponentName.packageName) 56 | if (callStaticMethod != null) { 57 | view.context.startActivity(intent, callStaticMethod.callMethod("toBundle") as Bundle) 58 | } 59 | } 60 | } 61 | mSystemShortcutMenu.hookAfterAllMethods("getMaxShortcutItemCount") { 62 | it.result = 5 63 | } 64 | mAppShortcutMenu.hookAfterAllMethods("getMaxShortcutItemCount") { 65 | it.result = 5 66 | } 67 | mSystemShortcutMenuItem.hookAfterAllMethods("createAllSystemShortcutMenuItems") { 68 | val mAllSystemShortcutMenuItems = mSystemShortcutMenuItem.getStaticObjectField("sAllSystemShortcutMenuItems") as Collection 69 | val mSmallWindowInstance = XposedHelpers.newInstance(mAppDetailsShortcutMenuItem) 70 | mSmallWindowInstance.callMethod("setShortTitle", moduleRes.getString(R.string.small_window)) 71 | XposedBridge.log(isDarkMode().toString()) 72 | mSmallWindowInstance.callMethod( 73 | "setIconDrawable", 74 | if (isDarkMode()) moduleRes.getDrawable(R.drawable.ic_task_small_window_dark) else moduleRes.getDrawable(R.drawable.ic_task_small_window_light) 75 | ) 76 | val sAllSystemShortcutMenuItems = ArrayList() 77 | sAllSystemShortcutMenuItems.add(mSmallWindowInstance) 78 | sAllSystemShortcutMenuItems.addAll(mAllSystemShortcutMenuItems) 79 | mSystemShortcutMenuItem.setStaticObjectField("sAllSystemShortcutMenuItems", sAllSystemShortcutMenuItems) 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/ShowDockIconTitle.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.yuk.miuiHomeR.mPrefsMap 4 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 5 | 6 | object ShowDockIconTitle : BaseHook() { 7 | override fun init() { 8 | 9 | if (!mPrefsMap.getBoolean("home_dock_icon_title")) return 10 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isHotseatsAppTitleHided") { 11 | it.result = false 12 | } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/TaskViewHorizontal.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.graphics.RectF 4 | import com.yuk.miuiHomeR.mPrefsMap 5 | import com.yuk.miuiHomeR.utils.ktx.callMethod 6 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 7 | import com.yuk.miuiHomeR.utils.ktx.findClass 8 | import com.yuk.miuiHomeR.utils.ktx.hookAfterMethod 9 | 10 | object TaskViewHorizontal : BaseHook() { 11 | override fun init() { 12 | 13 | val value1 = mPrefsMap.getInt("task_view_horizontal1", 100).toFloat() / 100 14 | val value2 = mPrefsMap.getInt("task_view_horizontal2", 100).toFloat() / 100 15 | if (value1 == 1f && value2 == 1f) return 16 | "com.miui.home.recents.views.TaskStackViewsAlgorithmHorizontal".hookAfterMethod( 17 | "scaleTaskView", RectF::class.java, 18 | ) { 19 | "com.miui.home.recents.util.Utilities".findClass().callStaticMethod( 20 | "scaleRectAboutCenter", it.args[0], if (it.thisObject.callMethod("isLandscapeVisually") as Boolean) value2 else value1 21 | ) 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/TaskViewVertical.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import android.graphics.RectF 4 | import com.github.kyuubiran.ezxhelper.init.InitFields.appContext 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | import com.yuk.miuiHomeR.utils.ktx.callStaticMethod 7 | import com.yuk.miuiHomeR.utils.ktx.findClass 8 | import com.yuk.miuiHomeR.utils.ktx.replaceMethod 9 | 10 | object TaskViewVertical : BaseHook() { 11 | override fun init() { 12 | 13 | val value = mPrefsMap.getInt("task_view_vertical", 100).toFloat() / 100 14 | if (value == -1f || value == 1f) return 15 | "com.miui.home.recents.views.TaskStackViewsAlgorithmVertical".replaceMethod( 16 | "scaleTaskView", RectF::class.java 17 | ) { 18 | "com.miui.home.recents.util.Utilities".findClass().callStaticMethod( 19 | "scaleRectAboutCenter", 20 | it.args[0], 21 | value * "com.miui.home.recents.util.Utilities".findClass().callStaticMethod("getTaskViewScale", appContext) as Float 22 | ) 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/UnlockAnim.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.utils.findMethod 4 | import com.github.kyuubiran.ezxhelper.utils.hookBefore 5 | import com.yuk.miuiHomeR.mPrefsMap 6 | 7 | object UnlockAnim : BaseHook() { 8 | override fun init() { 9 | 10 | if (!mPrefsMap.getBoolean("home_unlock_anim")) return 11 | findMethod("com.miui.home.launcher.compat.UserPresentAnimationCompatV12Phone") { 12 | name == "getSpringAnimator" && parameterCount == 6 13 | }.hookBefore { 14 | it.args[4] = 0.5f 15 | it.args[5] = 0.5f 16 | } 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/hook/UnlockHotseatIcon.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.hook 2 | 3 | import com.yuk.miuiHomeR.mPrefsMap 4 | import com.yuk.miuiHomeR.utils.ktx.hookBeforeMethod 5 | 6 | object UnlockHotseatIcon : BaseHook() { 7 | override fun init() { 8 | 9 | if (!mPrefsMap.getBoolean("home_unlock_hotseat")) return 10 | "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("getHotseatMaxCount") { 11 | it.result = 99 12 | } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/provider/SharedPrefsProvider.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.provider 2 | 3 | import android.content.ContentProvider 4 | import android.content.ContentValues 5 | import android.content.SharedPreferences 6 | import android.content.UriMatcher 7 | import android.content.res.AssetFileDescriptor 8 | import android.database.Cursor 9 | import android.database.MatrixCursor 10 | import android.net.Uri 11 | import android.os.ParcelFileDescriptor 12 | import com.yuk.miuiHomeR.utils.Helpers 13 | import com.yuk.miuiHomeR.utils.PrefsUtils 14 | import java.io.File 15 | import java.io.FileNotFoundException 16 | 17 | class SharedPrefsProvider : ContentProvider() { 18 | 19 | private var prefs: SharedPreferences? = null 20 | override fun onCreate(): Boolean { 21 | return try { 22 | prefs = context?.let { PrefsUtils.getSharedPrefs(it, true) } 23 | true 24 | } catch (throwable: Throwable) { 25 | false 26 | } 27 | } 28 | 29 | override fun query( 30 | uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String? 31 | ): Cursor? { 32 | val parts = uri.pathSegments 33 | val cursor = MatrixCursor(arrayOf("data")) 34 | when (uriMatcher.match(uri)) { 35 | 0 -> { 36 | cursor.newRow().add("data", prefs!!.getString(parts[1], "")) 37 | return cursor 38 | } 39 | 40 | 1 -> { 41 | cursor.newRow().add("data", prefs!!.getString(parts[1], parts[2])) 42 | return cursor 43 | } 44 | 45 | 2 -> { 46 | cursor.newRow().add("data", prefs!!.getInt(parts[1], parts[2].toInt())) 47 | return cursor 48 | } 49 | 50 | 3 -> { 51 | cursor.newRow().add("data", if (prefs!!.getBoolean(parts[1], parts[2].toInt() == 1)) 1 else 0) 52 | return cursor 53 | } 54 | 55 | 4 -> { 56 | val strings = prefs!!.getStringSet(parts[1], LinkedHashSet()) 57 | for (str in strings!!) cursor.newRow().add("data", str) 58 | return cursor 59 | } 60 | } 61 | return null 62 | } 63 | 64 | @Throws(FileNotFoundException::class) 65 | override fun openAssetFile(uri: Uri, mode: String): AssetFileDescriptor? { 66 | if (context == null) return null 67 | val parts = uri.pathSegments 68 | if (uriMatcher.match(uri) == 5) { 69 | var filename: String? = null 70 | if ("0" == parts[1]) filename = "test0.png" else if ("1" == parts[1]) filename = "test1.mp3" else if ("2" == parts[1]) filename = 71 | "test2.mp4" else if ("3" == parts[1] || "5" == parts[1]) filename = "test3.txt" else if ("4" == parts[1]) filename = "test4.zip" 72 | var afd: AssetFileDescriptor? = null 73 | if (filename != null) try { 74 | afd = context!!.assets.openFd(filename) 75 | } catch (t: Throwable) { 76 | t.printStackTrace() 77 | } 78 | return afd 79 | } else if (uriMatcher.match(uri) == 6) { 80 | val context = Helpers.getProtectedContext(context!!) 81 | val file = File(context.filesDir.toString() + "/shortcuts/" + parts[1] + "_shortcut.png") 82 | return if (!file.exists()) null else AssetFileDescriptor( 83 | ParcelFileDescriptor.open( 84 | file, ParcelFileDescriptor.MODE_READ_ONLY 85 | ), 0, AssetFileDescriptor.UNKNOWN_LENGTH 86 | ) 87 | } 88 | return null 89 | } 90 | 91 | override fun getType(uri: Uri): String? { 92 | return null 93 | } 94 | 95 | override fun insert(uri: Uri, values: ContentValues?): Uri? { 96 | return null 97 | } 98 | 99 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int { 100 | return 0 101 | } 102 | 103 | override fun update( 104 | uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array? 105 | ): Int { 106 | return 0 107 | } 108 | 109 | companion object { 110 | const val AUTHORITY = "com.yuk.miuiHomeR.provider.sharedprefs" 111 | private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH) 112 | 113 | init { 114 | uriMatcher.addURI(AUTHORITY, "string/*/", 0) 115 | uriMatcher.addURI(AUTHORITY, "string/*/*", 1) 116 | uriMatcher.addURI(AUTHORITY, "integer/*/*", 2) 117 | uriMatcher.addURI(AUTHORITY, "boolean/*/*", 3) 118 | uriMatcher.addURI(AUTHORITY, "stringset/*", 4) 119 | uriMatcher.addURI(AUTHORITY, "test/*", 5) 120 | uriMatcher.addURI(AUTHORITY, "shortcut_icon/*", 6) 121 | } 122 | } 123 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/AboutActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Bundle 7 | import androidx.fragment.app.Fragment 8 | import com.yuk.miuiHomeR.BuildConfig 9 | import com.yuk.miuiHomeR.R 10 | import com.yuk.miuiHomeR.ui.base.SubFragment 11 | import com.yuk.miuiHomeR.utils.ktx.getLocale 12 | import com.yuk.miuiHomeR.utils.ktx.setLocale 13 | import moralnorm.appcompat.app.PickerDragActivity 14 | import moralnorm.internal.utils.ViewUtils 15 | import moralnorm.preference.Preference 16 | 17 | class AboutActivity : PickerDragActivity() { 18 | 19 | override fun onCreate(bundle: Bundle?) { 20 | setTheme(if (ViewUtils.isNightMode(this)) R.style.Theme_AppCompat_Translucent_NoActionBar_NoAnimation_Dark else R.style.Theme_AppCompat_Translucent_NoActionBar_NoAnimation) 21 | super.onCreate(bundle) 22 | setDragContentView(R.layout.activity_main) 23 | supportFragmentManager.beginTransaction().replace(R.id.fragment_container, initFragment()).commit() 24 | } 25 | 26 | fun initFragment(): Fragment { 27 | return AboutFragment() 28 | } 29 | 30 | override fun attachBaseContext(base: Context) { 31 | super.attachBaseContext(setLocale(base, getLocale(base))) 32 | } 33 | 34 | class AboutFragment : SubFragment() { 35 | override fun getContentResId(): Int { 36 | return R.xml.prefs_about 37 | } 38 | 39 | override fun initPrefs() { 40 | val mVersion = findPreference("prefs_key_about_version") 41 | val mQQGroup = findPreference("prefs_key_about_join_qq_group") 42 | 43 | mVersion.title = "v" + BuildConfig.VERSION_NAME + " - " + BuildConfig.BUILD_TYPE 44 | 45 | mQQGroup.onPreferenceClickListener = Preference.OnPreferenceClickListener { 46 | joinQQGroup("g405srEn4hafy8xSJg1_EFJjxceLvpd7") 47 | true 48 | } 49 | } 50 | 51 | /**************** 52 | * 53 | * 调用 joinQQGroup() 即可发起手Q客户端申请加群 54 | * @param key 由官网生成的key 55 | * @return 返回true表示呼起手Q成功,返回false表示呼起失败 56 | */ 57 | private fun joinQQGroup(key: String): Boolean { 58 | val intent = Intent() 59 | intent.data = 60 | Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26jump_from%3Dwebapi%26k%3D$key") 61 | // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 62 | return try { 63 | startActivity(intent) 64 | true 65 | } catch (e: Exception) { 66 | // 未安装手Q或安装的版本不支持 67 | false 68 | } 69 | } 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/AppDrawerActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | import com.yuk.miuiHomeR.utils.ktx.atLeastAndroidS 8 | import moralnorm.preference.Preference 9 | 10 | class AppDrawerActivity : BaseAppCompatActivity() { 11 | 12 | override fun initFragment(): Fragment { 13 | setTitle(R.string.app_drawer) 14 | return AppDrawerFragment() 15 | } 16 | 17 | class AppDrawerFragment : SubFragment() { 18 | override fun getContentResId(): Int { 19 | return R.xml.prefs_app_drawer 20 | } 21 | 22 | override fun initPrefs() { 23 | val mAllAppsBlurVisible = findPreference("prefs_key_home_all_apps_blur") 24 | mAllAppsBlurVisible.isVisible = atLeastAndroidS() 25 | mAllAppsBlurVisible.isEnabled = mAllAppsBlurVisible.isVisible 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/DockActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | import com.yuk.miuiHomeR.utils.ktx.atLeastAndroidS 8 | import com.yuk.miuiHomeR.utils.ktx.isPadDevice 9 | import moralnorm.preference.Preference 10 | 11 | class DockActivity : BaseAppCompatActivity() { 12 | 13 | override fun initFragment(): Fragment { 14 | setTitle(R.string.dock_settings) 15 | return DockFragment() 16 | } 17 | 18 | class DockFragment : SubFragment() { 19 | override fun getContentResId(): Int { 20 | return R.xml.prefs_dock 21 | } 22 | 23 | override fun initPrefs() { 24 | val mDockVisible = findPreference("prefs_key_home_dock_blur") 25 | mDockVisible.isVisible = !isPadDevice() && atLeastAndroidS() 26 | mDockVisible.isEnabled = mDockVisible.isVisible 27 | val mDockTitleVisible = findPreference("prefs_key_home_dock_icon_title") 28 | mDockTitleVisible.isVisible = !isPadDevice() 29 | mDockTitleVisible.isEnabled = mDockTitleVisible.isVisible 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/FolderActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | import com.yuk.miuiHomeR.utils.ktx.atLeastAndroidS 8 | import moralnorm.preference.Preference 9 | 10 | class FolderActivity : BaseAppCompatActivity() { 11 | 12 | override fun initFragment(): Fragment { 13 | setTitle(R.string.folder) 14 | return FolderFragment() 15 | } 16 | 17 | class FolderFragment : SubFragment() { 18 | override fun getContentResId(): Int { 19 | return R.xml.prefs_folder 20 | } 21 | 22 | override fun initPrefs() { 23 | val mSmallFolderBlurVisible = findPreference("prefs_key_small_folder_blur") 24 | mSmallFolderBlurVisible.isVisible = atLeastAndroidS() 25 | mSmallFolderBlurVisible.isEnabled = mSmallFolderBlurVisible.isVisible 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/HomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | import com.yuk.miuiHomeR.utils.ktx.atLeastAndroidS 8 | import moralnorm.preference.Preference 9 | 10 | class HomeActivity : BaseAppCompatActivity() { 11 | 12 | override fun initFragment(): Fragment { 13 | setTitle(R.string.home) 14 | return HomeFragment() 15 | } 16 | 17 | class HomeFragment : SubFragment() { 18 | override fun getContentResId(): Int { 19 | return R.xml.prefs_home 20 | } 21 | 22 | override fun initPrefs() { 23 | val mShortcutBlurVisible = findPreference("prefs_key_home_shortcut_blur") 24 | mShortcutBlurVisible.isVisible = atLeastAndroidS() 25 | mShortcutBlurVisible.isEnabled = mShortcutBlurVisible.isVisible 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import android.content.Intent 4 | import android.content.SharedPreferences 5 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener 6 | import android.net.Uri 7 | import android.os.Bundle 8 | import android.os.FileObserver 9 | import android.util.Log 10 | import android.widget.ImageView 11 | import androidx.fragment.app.Fragment 12 | import com.yuk.miuiHomeR.R 13 | import com.yuk.miuiHomeR.provider.SharedPrefsProvider 14 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 15 | import com.yuk.miuiHomeR.ui.base.SubFragment 16 | import com.yuk.miuiHomeR.utils.Helpers 17 | import com.yuk.miuiHomeR.utils.PrefsUtils 18 | import com.yuk.miuiHomeR.utils.ktx.execShell 19 | import moralnorm.preference.Preference 20 | import java.io.File 21 | 22 | class MainActivity : BaseAppCompatActivity() { 23 | 24 | private var fileObserver: FileObserver? = null 25 | private var mPreferenceChangeListener: OnSharedPreferenceChangeListener? = null 26 | private var mActionBarMoreView: ImageView? = null 27 | 28 | override fun onCreate(savedInstanceState: Bundle?) { 29 | super.onCreate(savedInstanceState) 30 | appCompatActionBar.setDisplayHomeAsUpEnabled(intent.getBooleanExtra("homeAsUpEnabled", false)) 31 | initView() 32 | initData() 33 | } 34 | 35 | private fun initView() { 36 | mActionBarMoreView = ImageView(this) 37 | mActionBarMoreView!!.setImageResource(R.drawable.ic_settings) 38 | val actionBar = appCompatActionBar 39 | actionBar.endView = mActionBarMoreView 40 | mActionBarMoreView!!.setOnClickListener { 41 | startActivity( 42 | Intent(this, SettingsActivity::class.java) 43 | ) 44 | } 45 | } 46 | 47 | private fun initData() { 48 | mPreferenceChangeListener = OnSharedPreferenceChangeListener { sharedPreferences: SharedPreferences, s: String -> 49 | Log.i("prefs", "Changed: $s") 50 | val `val` = sharedPreferences.all[s] 51 | var path = "" 52 | if (`val` is String) path = "string/" else if (`val` is Set<*>) path = "stringset/" else if (`val` is Int) path = 53 | "integer/" else if (`val` is Boolean) path = "boolean/" 54 | contentResolver.notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/" + path + s), null) 55 | if (path != "") contentResolver.notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/pref/" + path + s), null) 56 | } 57 | PrefsUtils.mSharedPreferences?.registerOnSharedPreferenceChangeListener(mPreferenceChangeListener) 58 | Helpers.fixPermissionsAsync(applicationContext) 59 | try { 60 | fileObserver = object : FileObserver(File(PrefsUtils.sharedPrefsPath), CLOSE_WRITE) { 61 | override fun onEvent(event: Int, path: String?) { 62 | Helpers.fixPermissionsAsync(applicationContext) 63 | } 64 | } 65 | fileObserver?.startWatching() 66 | } catch (t: Throwable) { 67 | Log.e("prefs", "Failed to start FileObserver!") 68 | } 69 | } 70 | 71 | override fun initFragment(): Fragment { 72 | return MainFragment() 73 | } 74 | 75 | class MainFragment : SubFragment(), Preference.OnPreferenceClickListener { 76 | var mRebootHome: Preference? = null 77 | override fun getContentResId(): Int { 78 | return R.xml.prefs_main 79 | } 80 | 81 | override fun initPrefs() { 82 | mRebootHome = findPreference("reboot_home") 83 | mRebootHome?.onPreferenceClickListener = this 84 | } 85 | 86 | override fun onPreferenceClick(preference: Preference): Boolean { 87 | if (preference === mRebootHome) execShell("am force-stop com.miui.home && am force-stop com.yuk.miuiHomeR") 88 | return false 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/OtherActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | 8 | class OtherActivity : BaseAppCompatActivity() { 9 | 10 | override fun initFragment(): Fragment { 11 | setTitle(R.string.other_features) 12 | return OtherFeaturesFragment() 13 | } 14 | 15 | class OtherFeaturesFragment : SubFragment() { 16 | override fun getContentResId(): Int { 17 | return R.xml.prefs_other 18 | } 19 | 20 | override fun initPrefs() {} 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/RecentActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | import com.yuk.miuiHomeR.utils.ktx.checkMiuiVersion 8 | import moralnorm.preference.Preference 9 | 10 | class RecentActivity : BaseAppCompatActivity() { 11 | 12 | override fun initFragment(): Fragment { 13 | setTitle(R.string.recent) 14 | return RecentFragment() 15 | } 16 | 17 | class RecentFragment : SubFragment() { 18 | override fun getContentResId(): Int { 19 | return R.xml.prefs_recent 20 | } 21 | 22 | override fun initPrefs() { 23 | 24 | val mSmallWindowVisible = findPreference("prefs_key_home_hide_small_window") 25 | mSmallWindowVisible.isVisible = checkMiuiVersion() < 14f 26 | mSmallWindowVisible.isEnabled = mSmallWindowVisible.isVisible 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/SettingsActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import android.content.ComponentName 4 | import android.content.Intent 5 | import android.content.pm.PackageManager 6 | import androidx.fragment.app.Fragment 7 | import com.yuk.miuiHomeR.R 8 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 9 | import com.yuk.miuiHomeR.ui.base.SubFragment 10 | import com.yuk.miuiHomeR.utils.BackupUtils 11 | import com.yuk.miuiHomeR.utils.BackupUtils.backup 12 | import com.yuk.miuiHomeR.utils.BackupUtils.handleCreateDocument 13 | import com.yuk.miuiHomeR.utils.BackupUtils.handleReadDocument 14 | import com.yuk.miuiHomeR.utils.BackupUtils.recovery 15 | import com.yuk.miuiHomeR.utils.Locales 16 | import com.yuk.miuiHomeR.utils.PrefsUtils 17 | import moralnorm.preference.DropDownPreference 18 | import moralnorm.preference.Preference 19 | import moralnorm.preference.SwitchPreference 20 | import java.util.Locale 21 | 22 | class SettingsActivity : BaseAppCompatActivity() { 23 | 24 | override fun initFragment(): Fragment { 25 | setTitle(R.string.settings) 26 | return SettingsFragment() 27 | } 28 | 29 | class SettingsFragment : SubFragment(), Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { 30 | var mHideIcon: SwitchPreference? = null 31 | var mLocaleSelector: DropDownPreference? = null 32 | var mBackupSettings: Preference? = null 33 | var mRestoreSettings: Preference? = null 34 | override fun getContentResId(): Int { 35 | return R.xml.prefs_settings 36 | } 37 | 38 | override fun initPrefs() { 39 | val mLocaleName = ArrayList() 40 | mHideIcon = findPreference("prefs_key_settings_hide_icon") 41 | mLocaleSelector = findPreference("prefs_key_settings_language") 42 | mBackupSettings = findPreference("prefs_key_settings_backup") 43 | mRestoreSettings = findPreference("prefs_key_settings_restore") 44 | val displayLocaleTags = Locales.DISPLAY_LOCALES 45 | for (displayLocale in displayLocaleTags) { 46 | if (displayLocale == "SYSTEM") { 47 | mLocaleName.add(0, getString(R.string.system_default)) 48 | continue 49 | } 50 | val localizedLocale = Locale.forLanguageTag(displayLocale) 51 | mLocaleName.add(localizedLocale.getDisplayName(localizedLocale)) 52 | } 53 | mLocaleSelector?.setEntries(mLocaleName.toTypedArray()) 54 | mHideIcon?.onPreferenceChangeListener = this 55 | mLocaleSelector?.onPreferenceChangeListener = this 56 | mBackupSettings?.onPreferenceClickListener = this 57 | mRestoreSettings?.onPreferenceClickListener = this 58 | } 59 | 60 | override fun onPreferenceClick(preference: Preference): Boolean { 61 | if (preference === mBackupSettings) { 62 | PrefsUtils.mSharedPreferences?.let { backup(requireActivity(), it) } 63 | } else if (preference === mRestoreSettings) { 64 | PrefsUtils.mSharedPreferences?.let { recovery(requireActivity(), it) } 65 | } 66 | return true 67 | } 68 | 69 | override fun onPreferenceChange(preference: Preference, o: Any): Boolean { 70 | if (preference === mHideIcon) { 71 | val pm = requireActivity().packageManager 72 | val mComponentEnabledState: Int = if (o as Boolean) { 73 | PackageManager.COMPONENT_ENABLED_STATE_ENABLED 74 | } else { 75 | PackageManager.COMPONENT_ENABLED_STATE_DISABLED 76 | } 77 | pm.setComponentEnabledSetting( 78 | ComponentName(requireActivity(), MainActivity::class.java.name + "Alias"), 79 | mComponentEnabledState, 80 | PackageManager.DONT_KILL_APP 81 | ) 82 | } else if (preference === mLocaleSelector) { 83 | requireActivity().recreate() 84 | } 85 | return true 86 | } 87 | } 88 | 89 | @Deprecated("Deprecated in Java") 90 | public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 91 | super.onActivityResult(requestCode, resultCode, data) 92 | if (data == null) return 93 | when (requestCode) { 94 | BackupUtils.CREATE_DOCUMENT_CODE -> handleCreateDocument(this, data.data) 95 | BackupUtils.OPEN_DOCUMENT_CODE -> handleReadDocument(this, data.data) 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/WidgetActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui 2 | 3 | import androidx.fragment.app.Fragment 4 | import com.yuk.miuiHomeR.R 5 | import com.yuk.miuiHomeR.ui.base.BaseAppCompatActivity 6 | import com.yuk.miuiHomeR.ui.base.SubFragment 7 | 8 | class WidgetActivity : BaseAppCompatActivity() { 9 | 10 | override fun initFragment(): Fragment { 11 | setTitle(R.string.widget) 12 | return WidgetFragment() 13 | } 14 | 15 | class WidgetFragment : SubFragment() { 16 | override fun getContentResId(): Int { 17 | return R.xml.prefs_widget 18 | } 19 | 20 | override fun initPrefs() {} 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/base/BaseAppCompatActivity.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui.base 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.graphics.Color 6 | import android.os.Bundle 7 | import android.view.View 8 | import androidx.fragment.app.Fragment 9 | import com.yuk.miuiHomeR.R 10 | import com.yuk.miuiHomeR.utils.AppManager 11 | import com.yuk.miuiHomeR.utils.ktx.getLocale 12 | import com.yuk.miuiHomeR.utils.ktx.setLocale 13 | import moralnorm.appcompat.app.AppCompatActivity 14 | 15 | import moralnorm.internal.utils.ViewUtils 16 | import java.util.Locale 17 | 18 | abstract class BaseAppCompatActivity : AppCompatActivity() { 19 | 20 | private var mCurrentLocale: Locale? = null 21 | override fun onStart() { 22 | super.onStart() 23 | mCurrentLocale = resources.configuration.locales[0] 24 | } 25 | 26 | override fun onRestart() { 27 | super.onRestart() 28 | val locale: Locale = getLocale(this) 29 | if (locale != mCurrentLocale) { 30 | mCurrentLocale = locale 31 | recreate() 32 | } 33 | } 34 | 35 | override fun attachBaseContext(baseContext: Context) { 36 | super.attachBaseContext(setLocale(baseContext, getLocale(baseContext))) 37 | } 38 | 39 | override fun onCreate(savedInstanceState: Bundle?) { 40 | setTheme(if (ViewUtils.isNightMode(this)) R.style.AppTheme_Dark else R.style.AppTheme) 41 | super.onCreate(savedInstanceState) 42 | AppManager.getInstance().addActivity(this) 43 | setContentView(R.layout.activity_main) 44 | val res = resources 45 | val conf = res.configuration 46 | window.decorView.layoutDirection = conf.layoutDirection 47 | window.statusBarColor = Color.parseColor("#00000000") 48 | window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR 49 | supportFragmentManager.beginTransaction().replace(R.id.fragment_container, initFragment()).commit() 50 | } 51 | 52 | abstract fun initFragment(): Fragment 53 | 54 | fun startActivity(activity: AppCompatActivity, cls: Class<*>) { 55 | startActivity(Intent(activity, cls)) 56 | } 57 | 58 | override fun onDestroy() { 59 | super.onDestroy() 60 | AppManager.getInstance().removeActivity(this) 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/base/BasePreferenceFragment.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui.base 2 | 3 | import android.content.Context 4 | import android.os.Bundle 5 | import com.yuk.miuiHomeR.utils.PrefsUtils 6 | import com.yuk.miuiHomeR.utils.ktx.getLocale 7 | import com.yuk.miuiHomeR.utils.ktx.setLocale 8 | import moralnorm.preference.PreferenceFragmentCompat 9 | import moralnorm.preference.PreferenceManager 10 | 11 | open class BasePreferenceFragment : PreferenceFragmentCompat() { 12 | 13 | override fun onAttach(context: Context) { 14 | super.onAttach(setLocale(context, getLocale(context))) 15 | } 16 | 17 | fun onCreate(savedInstanceState: Bundle?, prefs_default: Int) { 18 | super.onCreate(savedInstanceState) 19 | try { 20 | preferenceManager.sharedPreferencesName = PrefsUtils.mPrefsName 21 | preferenceManager.sharedPreferencesMode = Context.MODE_PRIVATE 22 | preferenceManager.setStorageDeviceProtected() 23 | PreferenceManager.setDefaultValues(requireActivity(), prefs_default, false) 24 | } catch (throwable: Throwable) { 25 | throwable.printStackTrace() 26 | } 27 | } 28 | 29 | override fun onCreatePreferences(bundle: Bundle?, s: String?) {} 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/ui/base/SubFragment.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.ui.base 2 | 3 | import android.os.Bundle 4 | 5 | abstract class SubFragment : BasePreferenceFragment() { 6 | 7 | private var mContentResId = 0 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | mContentResId = getContentResId() 10 | if (mContentResId != 0) { 11 | super.onCreate(savedInstanceState, mContentResId) 12 | addPreferencesFromResource(mContentResId) 13 | } else { 14 | super.onCreate(savedInstanceState) 15 | } 16 | initPrefs() 17 | } 18 | 19 | abstract fun getContentResId(): Int 20 | abstract fun initPrefs() 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/AppManager.java: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils; 2 | 3 | import android.app.Activity; 4 | 5 | import java.util.Stack; 6 | 7 | public class AppManager { 8 | 9 | private static Stack activityStack; 10 | 11 | 12 | /** 13 | * 单一实例 14 | */ 15 | public static AppManager getInstance() { 16 | return SingleApp.INSTANCE; 17 | } 18 | 19 | /** 20 | * 获取指定的Activity 21 | */ 22 | public static Activity getActivity(Class cls) { 23 | if (activityStack != null) for (Activity activity : activityStack) { 24 | if (activity.getClass().equals(cls)) { 25 | return activity; 26 | } 27 | } 28 | return null; 29 | } 30 | 31 | /** 32 | * 添加Activity到堆栈 33 | */ 34 | public void addActivity(Activity activity) { 35 | if (activityStack == null) { 36 | activityStack = new Stack<>(); 37 | } 38 | activityStack.add(activity); 39 | } 40 | 41 | /** 42 | * 移除Activity 43 | */ 44 | public void removeActivity(Activity activity) { 45 | activityStack.remove(activity); 46 | } 47 | 48 | /** 49 | * 获取当前显示Activity(堆栈中最后一个传入的activity) 50 | */ 51 | public Activity getLastActivity() { 52 | return activityStack.lastElement(); 53 | } 54 | 55 | /** 56 | * 获取所有Activity 57 | */ 58 | public Stack getAllActivityStacks() { 59 | return activityStack; 60 | } 61 | 62 | /** 63 | * 结束指定的Activity 64 | */ 65 | public void finishActivity(Activity activity) { 66 | if (activity != null) { 67 | if (!activity.isFinishing()) { 68 | activity.finish(); 69 | activityStack.remove(activity); 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * 结束指定类名的Activity 76 | */ 77 | public void finishActivity(Class cls) { 78 | for (Activity activity : activityStack) { 79 | if (activity.getClass().equals(cls)) { 80 | finishActivity(activity); 81 | break; 82 | } 83 | } 84 | } 85 | 86 | /** 87 | * 结束除当前传入以外所有Activity 88 | */ 89 | public void finishOthersActivity(Class cls) { 90 | if (activityStack != null) for (Activity activity : activityStack) { 91 | if (!activity.getClass().equals(cls)) { 92 | activity.finish(); 93 | } 94 | } 95 | } 96 | 97 | /** 98 | * 结束所有Activity 99 | */ 100 | public void finishAllActivity() { 101 | if (activityStack != null) for (Activity activity : activityStack) { 102 | activity.finish(); 103 | } 104 | activityStack.clear(); 105 | } 106 | 107 | /** 108 | * 退出应用程序 109 | */ 110 | public void AppExit() { 111 | try { 112 | finishAllActivity(); 113 | android.os.Process.killProcess(android.os.Process.myPid());// 杀死该应用进程 114 | System.exit(0); 115 | } catch (Exception ignore) { 116 | } 117 | } 118 | 119 | public static class SingleApp { 120 | public static final AppManager INSTANCE = new AppManager(); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/BackupUtils.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import android.content.SharedPreferences 6 | import android.net.Uri 7 | import org.json.JSONObject 8 | import java.io.BufferedReader 9 | import java.io.BufferedWriter 10 | import java.io.InputStreamReader 11 | import java.io.OutputStreamWriter 12 | import java.time.LocalDateTime 13 | 14 | object BackupUtils { 15 | const val CREATE_DOCUMENT_CODE = 255774 16 | const val OPEN_DOCUMENT_CODE = 277451 17 | 18 | private lateinit var sharedPreferences: SharedPreferences 19 | 20 | fun backup(activity: Activity, sp: SharedPreferences) { 21 | sharedPreferences = sp 22 | saveFile(activity, "MiuiHomeR_${LocalDateTime.now()}.json") 23 | } 24 | 25 | fun recovery(activity: Activity, sp: SharedPreferences) { 26 | sharedPreferences = sp 27 | openFile(activity) 28 | } 29 | 30 | private fun openFile(activity: Activity) { 31 | val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) 32 | intent.addCategory(Intent.CATEGORY_OPENABLE) 33 | intent.type = "application/json" 34 | intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false) 35 | activity.startActivityForResult(intent, OPEN_DOCUMENT_CODE) 36 | } 37 | 38 | 39 | private fun saveFile(activity: Activity, fileName: String) { 40 | val intent = Intent(Intent.ACTION_CREATE_DOCUMENT) 41 | intent.addCategory(Intent.CATEGORY_OPENABLE) 42 | intent.type = "application/json" 43 | intent.putExtra(Intent.EXTRA_TITLE, fileName) 44 | activity.startActivityForResult(intent, CREATE_DOCUMENT_CODE) 45 | } 46 | 47 | fun handleReadDocument(activity: Activity, data: Uri?) { 48 | val edit = sharedPreferences.edit() 49 | val uri = data ?: return 50 | try { 51 | activity.contentResolver.openInputStream(uri)?.let { loadFile -> 52 | BufferedReader(InputStreamReader(loadFile)).apply { 53 | val sb = StringBuffer() 54 | var line = readLine() 55 | while (line != null) { 56 | sb.append(line) 57 | line = readLine() 58 | } 59 | val read = sb.toString() 60 | JSONObject(read).apply { 61 | val key = keys() 62 | while (key.hasNext()) { 63 | val keys = key.next() 64 | when (val value = get(keys)) { 65 | is String -> if (value.startsWith("Float:")) edit.putFloat( 66 | keys, value.substring(value.indexOf("Float:")).toFloat() / 1000 67 | ) else edit.putString(keys, value) 68 | 69 | is Boolean -> edit.putBoolean(keys, value) 70 | is Int -> edit.putInt(keys, value) 71 | } 72 | } 73 | } 74 | close() 75 | } 76 | } 77 | edit.apply() 78 | } catch (_: Throwable) { 79 | } 80 | } 81 | 82 | fun handleCreateDocument(activity: Activity, data: Uri?) { 83 | val uri = data ?: return 84 | try { 85 | activity.contentResolver.openOutputStream(uri)?.let { saveFile -> 86 | BufferedWriter(OutputStreamWriter(saveFile)).apply { 87 | write(JSONObject().also { 88 | for (entry: Map.Entry in sharedPreferences.all) { 89 | when (entry.value) { 90 | Float -> it.put(entry.key, "Float:" + (entry.value as Float * 1000).toInt().toString()) 91 | else -> if (entry.key != "prefs_key_settings_hide_icon") it.put(entry.key, entry.value) 92 | } 93 | } 94 | }.toString()) 95 | close() 96 | } 97 | } 98 | } catch (_: Throwable) { 99 | } 100 | } 101 | 102 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/Helpers.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.res.Configuration 6 | import android.os.AsyncTask 7 | import com.yuk.miuiHomeR.BuildConfig 8 | import java.io.File 9 | 10 | object Helpers { 11 | const val mAppModulePkg = BuildConfig.APPLICATION_ID 12 | 13 | @Synchronized 14 | fun getProtectedContext(context: Context): Context { 15 | return getProtectedContext(context, null) 16 | } 17 | 18 | @Synchronized 19 | fun getProtectedContext(context: Context, config: Configuration?): Context { 20 | return try { 21 | val mContext = if (context.isDeviceProtectedStorage) context else context.createDeviceProtectedStorageContext() 22 | if (config == null) mContext else mContext.createConfigurationContext(config) 23 | } catch (t: Throwable) { 24 | context 25 | } 26 | } 27 | 28 | @SuppressLint("SetWorldReadable", "SetWorldWritable") 29 | fun fixPermissionsAsync(context: Context) { 30 | AsyncTask.execute { 31 | try { 32 | Thread.sleep(500) 33 | } catch (ignore: Throwable) { 34 | } 35 | val pkgFolder = context.dataDir 36 | if (pkgFolder.exists()) { 37 | pkgFolder.setExecutable(true, false) 38 | pkgFolder.setReadable(true, false) 39 | pkgFolder.setWritable(true, false) 40 | } 41 | val sharedPrefsFolder = File(PrefsUtils.sharedPrefsPath!!) 42 | if (sharedPrefsFolder.exists()) { 43 | sharedPrefsFolder.setExecutable(true, false) 44 | sharedPrefsFolder.setReadable(true, false) 45 | sharedPrefsFolder.setWritable(true, false) 46 | } 47 | val sharedPrefsFile = File(PrefsUtils.sharedPrefsFile!!) 48 | if (sharedPrefsFile.exists()) { 49 | sharedPrefsFile.setReadable(true, false) 50 | sharedPrefsFile.setExecutable(true, false) 51 | sharedPrefsFile.setWritable(true, false) 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/PrefsMap.java: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.LinkedHashSet; 5 | import java.util.Set; 6 | 7 | public class PrefsMap extends HashMap { 8 | 9 | public Object getObject(String key, Object defValue) { 10 | return get(key) == null ? defValue : get(key); 11 | } 12 | 13 | public int getInt(String key, int defValue) { 14 | key = "prefs_key_" + key; 15 | return get(key) == null ? defValue : (Integer) get(key); 16 | } 17 | 18 | public String getString(String key, String defValue) { 19 | key = "prefs_key_" + key; 20 | return get(key) == null ? defValue : (String) get(key); 21 | } 22 | 23 | public int getStringAsInt(String key, int defValue) { 24 | key = "prefs_key_" + key; 25 | return get(key) == null ? defValue : Integer.parseInt((String) get(key)); 26 | } 27 | 28 | @SuppressWarnings("unchecked") 29 | public Set getStringSet(String key) { 30 | key = "prefs_key_" + key; 31 | return get(key) == null ? new LinkedHashSet<>() : (Set) get(key); 32 | } 33 | 34 | public boolean getBoolean(String key) { 35 | key = "prefs_key_" + key; 36 | return get(key) != null && (Boolean) get(key); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/PrefsUtils.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.SharedPreferences 6 | import com.yuk.miuiHomeR.utils.Helpers.getProtectedContext 7 | import java.io.File 8 | 9 | object PrefsUtils { 10 | const val mPrefsName = "MiuiHome_Config" 11 | private var mPrefsPathCurrent: String? = null 12 | private var mPrefsFileCurrent: String? = null 13 | var mSharedPreferences: SharedPreferences? = null 14 | private const val mPrefsPath = "/data/user_de/0/" + Helpers.mAppModulePkg + "/shared_prefs" 15 | private const val mPrefsFile = "$mPrefsPath/$mPrefsName.xml" 16 | 17 | @SuppressLint("WorldReadableFiles") 18 | fun getSharedPrefs(context: Context, protectedStorage: Boolean, multiProcess: Boolean): SharedPreferences { 19 | var c = context 20 | if (protectedStorage) c = getProtectedContext(c) 21 | return try { 22 | c.getSharedPreferences( 23 | mPrefsName, if (multiProcess) Context.MODE_MULTI_PROCESS or Context.MODE_WORLD_READABLE else Context.MODE_WORLD_READABLE 24 | ) 25 | } catch (t: Throwable) { 26 | c.getSharedPreferences(mPrefsName, if (multiProcess) Context.MODE_MULTI_PROCESS or Context.MODE_PRIVATE else Context.MODE_PRIVATE) 27 | } 28 | } 29 | 30 | fun getSharedPrefs(context: Context, protectedStorage: Boolean): SharedPreferences { 31 | return getSharedPrefs(context, protectedStorage, false) 32 | } 33 | 34 | val sharedPrefsPath: String? 35 | get() = if (mPrefsPathCurrent == null) try { 36 | val mFile = mSharedPreferences!!.javaClass.getDeclaredField("mFile") 37 | mFile.isAccessible = true 38 | mPrefsPathCurrent = (mFile[mSharedPreferences] as File).parentFile?.absolutePath 39 | mPrefsPathCurrent 40 | } catch (t: Throwable) { 41 | print("Test$t") 42 | mPrefsPath 43 | } else mPrefsPathCurrent 44 | val sharedPrefsFile: String? 45 | get() { 46 | if (mPrefsFileCurrent == null) return try { 47 | val fFile = mSharedPreferences!!.javaClass.getDeclaredField("mFile") 48 | fFile.isAccessible = true 49 | mPrefsFileCurrent = (fFile[mSharedPreferences] as File).absolutePath 50 | println("Test: mPrefsFileCurrent") 51 | mPrefsFileCurrent 52 | } catch (t: Throwable) { 53 | println("Test: mPrefsFile$t") 54 | mPrefsFile 55 | } else println("Test: mPrefsFileCurrent2") 56 | return mPrefsFileCurrent 57 | } 58 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/ResourcesHookData.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils 2 | 3 | data class ResourcesHookData(val type: String, val afterValue: Any) 4 | -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/ResourcesHookMap.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils 2 | 3 | class ResourcesHookMap : HashMap() { 4 | fun isKeyExist(key: String): Boolean = getOrDefault(key, null) != null 5 | } -------------------------------------------------------------------------------- /app/src/main/java/com/yuk/miuiHomeR/utils/ktx/AppUtil.kt: -------------------------------------------------------------------------------- 1 | package com.yuk.miuiHomeR.utils.ktx 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Context 5 | import android.content.res.Configuration 6 | import android.content.res.Resources 7 | import android.os.Build 8 | import android.text.TextUtils 9 | import android.util.Log 10 | import android.util.TypedValue 11 | import androidx.appcompat.app.AppCompatDelegate 12 | import androidx.core.os.LocaleListCompat 13 | import com.github.kyuubiran.ezxhelper.init.InitFields 14 | import com.yuk.miuiHomeR.utils.PrefsUtils.getSharedPrefs 15 | import moralnorm.internal.utils.DeviceHelper 16 | import java.io.DataOutputStream 17 | import java.util.* 18 | 19 | fun dp2px(dpValue: Float): Int = TypedValue.applyDimension( 20 | TypedValue.COMPLEX_UNIT_DIP, dpValue, InitFields.appContext.resources.displayMetrics 21 | ).toInt() 22 | 23 | fun px2dp(pxValue: Int): Int = (pxValue / InitFields.appContext.resources.displayMetrics.density + 0.5f).toInt() 24 | 25 | fun getDensityDpi(): Int = 26 | (InitFields.appContext.resources.displayMetrics.widthPixels / InitFields.appContext.resources.displayMetrics.density).toInt() 27 | 28 | fun isDarkMode(): Boolean = 29 | InitFields.appContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES 30 | 31 | @SuppressLint("PrivateApi") 32 | @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") 33 | fun getProp(mKey: String): String = 34 | Class.forName("android.os.SystemProperties").getMethod("get", String::class.java).invoke(Class.forName("android.os.SystemProperties"), mKey) 35 | .toString() 36 | 37 | @SuppressLint("PrivateApi") 38 | fun getProp(mKey: String, defaultValue: Boolean): Boolean = 39 | Class.forName("android.os.SystemProperties").getMethod("getBoolean", String::class.java, Boolean::class.javaPrimitiveType) 40 | .invoke(Class.forName("android.os.SystemProperties"), mKey, defaultValue) as Boolean 41 | 42 | fun checkVersionName(): String = InitFields.appContext.packageManager.getPackageInfo( 43 | InitFields.appContext.packageName, 0 44 | ).versionName 45 | 46 | fun isAlpha(): Boolean = InitFields.appContext.packageManager.getPackageInfo( 47 | InitFields.appContext.packageName, 0 48 | ).versionName.contains("ALPHA", ignoreCase = true) 49 | 50 | fun isPadDevice(): Boolean = DeviceHelper.isTablet() || DeviceHelper.isFoldDevice() 51 | 52 | fun atLeastAndroidS(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S 53 | 54 | fun atLeastAndroidT(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU 55 | 56 | fun checkVersionCode(): Long = InitFields.appContext.packageManager.getPackageInfo( 57 | InitFields.appContext.packageName, 0 58 | ).longVersionCode 59 | 60 | fun checkMiuiVersion(): Float = when (getProp("ro.miui.ui.version.name")) { 61 | "V140" -> 14f 62 | "V130" -> 13f 63 | "V125" -> 12.5f 64 | "V12" -> 12f 65 | "V11" -> 11f 66 | "V10" -> 10f 67 | else -> 0f 68 | } 69 | 70 | fun checkAndroidVersion(): String = getProp("ro.build.version.release") 71 | 72 | /** 73 | * 执行 Shell 命令 74 | * @param command Shell 命令 75 | */ 76 | fun execShell(command: String) { 77 | try { 78 | val p = Runtime.getRuntime().exec("su") 79 | val outputStream = p.outputStream 80 | val dataOutputStream = DataOutputStream(outputStream) 81 | dataOutputStream.writeBytes(command) 82 | dataOutputStream.flush() 83 | dataOutputStream.close() 84 | outputStream.close() 85 | } catch (t: Throwable) { 86 | t.printStackTrace() 87 | } 88 | } 89 | 90 | @SuppressLint("DiscouragedApi") 91 | fun getCornerRadiusTop(): Int { 92 | val resourceId = InitFields.appContext.resources.getIdentifier( 93 | "rounded_corner_radius_top", "dimen", "android" 94 | ) 95 | return if (resourceId > 0) { 96 | InitFields.appContext.resources.getDimensionPixelSize(resourceId) 97 | } else 100 98 | } 99 | 100 | fun setLocale(context: Context, locale: Locale): Context { 101 | var tmpLocale: Locale = locale 102 | if ("und" == locale.toLanguageTag() || "system" == locale.toLanguageTag()) { 103 | tmpLocale = Resources.getSystem().configuration.locales[0] 104 | } 105 | val configuration = context.resources.configuration 106 | configuration.setLocale(tmpLocale) 107 | Log.d("AppUtil", "setLocale: ${tmpLocale.toLanguageTag()}") 108 | if (atLeastAndroidT()) { 109 | AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tmpLocale.toLanguageTag())) 110 | } 111 | return context.createConfigurationContext(configuration) 112 | } 113 | 114 | fun getLocale(context: Context): Locale { 115 | val pref = getSharedPrefs(context, true) 116 | val tag: String? = pref.getString("prefs_key_settings_language", "SYSTEM") 117 | Log.d("AppUtil", "getLocale: tag=$tag") 118 | return if (tag == null || TextUtils.isEmpty(tag) || "SYSTEM" == tag) { 119 | val sysLang = Resources.getSystem().configuration.locales[0].toLanguageTag().trim() 120 | Log.d("AppUtil", "getLocale: sysLang=$sysLang") 121 | Locale.forLanguageTag(sysLang) 122 | } else Locale.forLanguageTag(tag) 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/BackgroundBlurDrawableExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur 2 | 3 | import android.os.Build 4 | import androidx.annotation.RequiresApi 5 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable 6 | import org.lsposed.hiddenapibypass.HiddenApiBypass 7 | 8 | @RequiresApi(Build.VERSION_CODES.S) 9 | fun BackgroundBlurDrawable.setColor(color: Int) { 10 | HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setColor", color) 11 | } 12 | 13 | @RequiresApi(Build.VERSION_CODES.S) 14 | fun BackgroundBlurDrawable.setBlurRadius(blurRadius: Int) { 15 | HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setBlurRadius", blurRadius) 16 | } 17 | 18 | @RequiresApi(Build.VERSION_CODES.S) 19 | fun BackgroundBlurDrawable.setCornerRadius( 20 | cornerRadiusTL: Float, 21 | cornerRadiusTR: Float, 22 | cornerRadiusBL: Float, 23 | cornerRadiusBR: Float 24 | ) { 25 | HiddenApiBypass.invoke( 26 | BackgroundBlurDrawable::class.java, 27 | this, 28 | "setCornerRadius", 29 | cornerRadiusTL, 30 | cornerRadiusTR, 31 | cornerRadiusBL, 32 | cornerRadiusBR 33 | ) 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/BlurFrameLayout.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur 2 | 3 | import android.content.Context 4 | import android.os.Build 5 | import android.widget.FrameLayout 6 | import androidx.annotation.RequiresApi 7 | 8 | class BlurFrameLayout constructor(context: Context) : FrameLayout(context) { 9 | @RequiresApi(Build.VERSION_CODES.S) 10 | val blurController: SystemBlurController = SystemBlurController(this) 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/BlurLinearLayout.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur 2 | 3 | import android.content.Context 4 | import android.os.Build 5 | import android.widget.LinearLayout 6 | import androidx.annotation.RequiresApi 7 | 8 | class BlurLinearLayout constructor(context: Context) : LinearLayout(context) { 9 | @RequiresApi(Build.VERSION_CODES.S) 10 | val blurController: SystemBlurController = SystemBlurController(this) 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/SystemBlurController.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur 2 | 3 | import android.content.Context 4 | import android.graphics.Color 5 | import android.graphics.drawable.ShapeDrawable 6 | import android.graphics.drawable.shapes.RoundRectShape 7 | import android.os.Build 8 | import android.view.View 9 | import android.view.WindowManager 10 | import androidx.annotation.RequiresApi 11 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable 12 | import com.yuk.miuiHomeR.mPrefsMap 13 | import com.zhenxiang.blur.model.CornersRadius 14 | import java.util.function.Consumer 15 | 16 | @RequiresApi(Build.VERSION_CODES.S) 17 | class SystemBlurController( 18 | private val view: View, 19 | backgroundColour: Int = if (mPrefsMap.getInt("blur_view_color", -1) != -1) mPrefsMap.getInt("blur_view_color", -1) 20 | else Color.parseColor("#44FFFFFF"), 21 | blurRadius: Int = mPrefsMap.getInt("home_blur_radius", 100), 22 | cornerRadius: CornersRadius = CornersRadius.all(0f), 23 | ) : View.OnAttachStateChangeListener { 24 | 25 | private var windowManager: WindowManager? = null 26 | private val crossWindowBlurListener = Consumer { blurEnabled = it } 27 | private var blurEnabled: Boolean = false 28 | set(value) { 29 | if (value != field) { 30 | field = value 31 | updateBackgroundColour() 32 | updateBlurRadius() 33 | } 34 | } 35 | var backgroundColour = backgroundColour 36 | set(value) { 37 | field = value 38 | updateBackgroundColour() 39 | } 40 | var blurRadius = blurRadius 41 | set(value) { 42 | field = value 43 | updateBlurRadius() 44 | } 45 | var cornerRadius = cornerRadius 46 | set(value) { 47 | field = value 48 | when (val bg = view.background) { 49 | is BackgroundBlurDrawable -> setCornerRadius(bg, value) 50 | is ShapeDrawable -> bg.shape = getShapeFromCorners(value) 51 | } 52 | } 53 | 54 | init { 55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { 56 | // On api 31 and above background init is done in onViewAttachedToWindow 57 | view.addOnAttachStateChangeListener(this) 58 | } else { 59 | // On pre api 31 init background here 60 | val shape = ShapeDrawable() 61 | shape.shape = getShapeFromCorners(cornerRadius) 62 | shape.paint.color = backgroundColour 63 | view.background = shape 64 | } 65 | } 66 | 67 | override fun onViewAttachedToWindow(v: View) { 68 | windowManager = getWindowManager(view.context).apply { 69 | blurEnabled = isCrossWindowBlurEnabled 70 | addCrossWindowBlurEnabledListener(crossWindowBlurListener) 71 | } 72 | view.createBackgroundBlurDrawable()?.let { 73 | // Configure blur drawable with current values 74 | it.setColor(backgroundColour) 75 | it.setBlurRadius(blurRadius) 76 | setCornerRadius(it, cornerRadius) 77 | view.background = it 78 | } 79 | } 80 | 81 | override fun onViewDetachedFromWindow(_v: View) { 82 | // Clear blur drawable 83 | if (view.background is BackgroundBlurDrawable) { 84 | view.background = null 85 | } 86 | windowManager?.removeCrossWindowBlurEnabledListener(crossWindowBlurListener) 87 | windowManager = null 88 | } 89 | 90 | private fun updateBackgroundColour() { 91 | val bg = view.background 92 | when (bg) { 93 | is BackgroundBlurDrawable -> bg.setColor(backgroundColour) 94 | is ShapeDrawable -> bg.paint.color = backgroundColour 95 | } 96 | bg?.invalidateSelf() 97 | } 98 | 99 | private fun updateBlurRadius() { 100 | val bg = view.background 101 | if (bg is BackgroundBlurDrawable) { 102 | bg.setBlurRadius(if (blurEnabled) blurRadius else 0) 103 | } 104 | } 105 | 106 | private fun setCornerRadius(blurDrawable: BackgroundBlurDrawable, corners: CornersRadius) { 107 | blurDrawable.setCornerRadius( 108 | corners.topLeft, corners.topRight, corners.bottomLeft, corners.bottomRight 109 | ) 110 | } 111 | 112 | private fun getShapeFromCorners(corners: CornersRadius): RoundRectShape { 113 | return RoundRectShape(getCornersFloatArray(corners), null, null) 114 | } 115 | 116 | private fun getCornersFloatArray(corners: CornersRadius): FloatArray { 117 | return floatArrayOf( 118 | corners.topLeft, 119 | corners.topLeft, 120 | corners.topRight, 121 | corners.topRight, 122 | corners.bottomRight, 123 | corners.bottomRight, 124 | corners.bottomLeft, 125 | corners.bottomLeft 126 | ) 127 | } 128 | 129 | private fun getWindowManager(context: Context): WindowManager { 130 | return context.getSystemService(Context.WINDOW_SERVICE) as WindowManager 131 | } 132 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/ViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur 2 | 3 | import android.os.Build 4 | import android.util.Log 5 | import android.view.View 6 | import android.view.ViewRootImpl 7 | import androidx.annotation.RequiresApi 8 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable 9 | import org.lsposed.hiddenapibypass.HiddenApiBypass 10 | 11 | @RequiresApi(Build.VERSION_CODES.S) 12 | fun View.createBackgroundBlurDrawable(): BackgroundBlurDrawable? { 13 | 14 | return try { 15 | val getViewRootImpl = 16 | HiddenApiBypass.invoke(View::class.java, this, "getViewRootImpl") as ViewRootImpl 17 | HiddenApiBypass.invoke( 18 | ViewRootImpl::class.java, 19 | getViewRootImpl, 20 | "createBackgroundBlurDrawable" 21 | ) as BackgroundBlurDrawable 22 | } catch (e: Exception) { 23 | Log.w(null, e) 24 | null 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zhenxiang/blur/model/CornerRadius.kt: -------------------------------------------------------------------------------- 1 | package com.zhenxiang.blur.model 2 | 3 | data class CornersRadius( 4 | val topLeft: Float, 5 | val topRight: Float, 6 | val bottomLeft: Float, 7 | val bottomRight: Float, 8 | ) { 9 | 10 | companion object { 11 | fun all(radius: Float): CornersRadius { 12 | return CornersRadius(radius, radius, radius, radius) 13 | } 14 | 15 | fun custom( 16 | topLeft: Float, topRight: Float, bottomLeft: Float, bottomRight: Float 17 | ): CornersRadius { 18 | return CornersRadius(topLeft, topRight, bottomLeft, bottomRight) 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-440dpi/ic_moralnorm.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/src/main/res/drawable-440dpi/ic_moralnorm.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-440dpi/ic_yukonga.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/app/src/main/res/drawable-440dpi/ic_yukonga.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 24 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_task_small_window_dark.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_task_small_window_light.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 23 | 24 | 31 | 32 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/preference_round_layout.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 26 | 27 | 36 | 37 | 42 | 43 | 44 | 45 | 53 | 54 | 63 | 64 | 74 | 75 | 76 | 77 | 78 | 87 | 88 | 96 | 97 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ccffffff 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | com.miui.home 5 | 6 | 7 | 8 | @string/complete_blur 9 | @string/test_blur 10 | @string/simple_blur 11 | @string/none_blur 12 | @string/none_blur_simple_anim 13 | 14 | 15 | 16 | 0 17 | 1 18 | 2 19 | 3 20 | 4 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #cc000000 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 12 | 13 | 22 | 23 | 27 | 28 | 34 | 35 | 41 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 16 | 19 | 20 | 21 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 51 | 52 | 53 | 54 | 57 | 58 | 59 | 60 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 72 | 73 | 76 | 77 | 78 | 81 | 82 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_app_drawer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 16 | 17 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_dock.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 20 | 21 | 22 | 30 | 31 | 32 | 41 | 42 | 43 | 51 | 52 | 53 | 61 | 62 | 63 | 72 | 73 | 74 | 83 | 84 | 85 | 93 | 94 | 95 | 99 | 100 | 101 | 109 | 110 | 111 | 119 | 120 | 121 | 125 | 126 | 127 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 13 | 17 | 18 | 22 | 23 | 27 | 28 | 32 | 33 | 37 | 38 | 42 | 43 | 47 | 48 | 52 | 53 | 57 | 58 | 66 | 67 | 74 | 75 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_other.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 17 | 18 | 22 | 23 | 28 | 29 | 36 | 37 | 44 | 45 | 53 | 54 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_recent.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 13 | 14 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | 39 | 40 | 44 | 45 | 49 | 50 | 54 | 55 | 62 | 63 | 70 | 71 | 79 | 80 | 88 | 89 | 97 | 98 | 106 | 107 | 114 | 115 | 121 | 122 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/xml/prefs_widget.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 15 | 16 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") version "7.4.0" apply false 3 | id("com.android.library") version "7.4.0" apply false 4 | id("org.jetbrains.kotlin.android") version "1.8.10" apply false 5 | id("dev.rikka.tools.autoresconfig") version "1.2.2" apply false 6 | } 7 | 8 | tasks.register("clean").configure { 9 | delete(rootProject.buildDir) 10 | } 11 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /app/src/main/res/values/strings.xml 3 | translation: /app/src/main/res/values-%two_letters_code%/strings.xml 4 | -------------------------------------------------------------------------------- /dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gradle 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | target-branch: main 8 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | #android.enableJetifier=true 20 | android.enableR8.fullMode=true 21 | android.enableAppCompileTimeRClass=true 22 | android.nonTransitiveRClass=true 23 | org.gradle.caching=true 24 | org.gradle.parallel=true 25 | org.gradle.vfs.watch=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qqlittleice/MiuiHome_R/9f3a298df6427b3a8ea6a47aaabfa0a56c4dd11e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionPath=wrapper/dists 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if %ERRORLEVEL% equ 0 goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if %ERRORLEVEL% equ 0 goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | set EXIT_CODE=%ERRORLEVEL% 84 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 85 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 86 | exit /b %EXIT_CODE% 87 | 88 | :mainEnd 89 | if "%OS%"=="Windows_NT" endlocal 90 | 91 | :omega 92 | -------------------------------------------------------------------------------- /hidden-api/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /hidden-api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.library") 3 | id("org.jetbrains.kotlin.android") 4 | } 5 | 6 | android { 7 | compileSdk = 33 8 | namespace = "com.android.internal" 9 | buildTypes { 10 | release { 11 | isMinifyEnabled = false 12 | setProguardFiles(listOf(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")) 13 | } 14 | } 15 | compileOptions { 16 | sourceCompatibility = JavaVersion.VERSION_11 17 | targetCompatibility = JavaVersion.VERSION_11 18 | } 19 | kotlinOptions { 20 | jvmTarget = JavaVersion.VERSION_11.majorVersion 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation("androidx.annotation:annotation:1.5.0") 26 | } 27 | -------------------------------------------------------------------------------- /hidden-api/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /hidden-api/src/main/java/android/view/ViewRootImpl.java: -------------------------------------------------------------------------------- 1 | package android.view; 2 | 3 | import android.os.Build; 4 | 5 | import androidx.annotation.RequiresApi; 6 | 7 | import com.android.internal.graphics.drawable.BackgroundBlurDrawable; 8 | 9 | public class ViewRootImpl { 10 | @RequiresApi(Build.VERSION_CODES.S) 11 | public BackgroundBlurDrawable createBackgroundBlurDrawable() { 12 | throw new RuntimeException("Stub!"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /hidden-api/src/main/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java: -------------------------------------------------------------------------------- 1 | package com.android.internal.graphics.drawable; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.os.Build; 5 | 6 | import androidx.annotation.RequiresApi; 7 | 8 | @RequiresApi(Build.VERSION_CODES.S) 9 | public abstract class BackgroundBlurDrawable extends Drawable { } 10 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | 9 | dependencyResolutionManagement { 10 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 11 | repositories { 12 | google() 13 | mavenCentral() 14 | maven("https://jitpack.io") 15 | maven("https://api.xposed.info") 16 | } 17 | } 18 | 19 | include(":app", ":hidden-api") 20 | rootProject.name = "MiuiHomeR" 21 | --------------------------------------------------------------------------------